Emmet Cheatsheet - Emmet Abbreviation & Syntax Reference
Emmet works by parsing a short abbreviation into a tree and expanding it into text, which means it shines on regular, predictable markup: navigation items, table rows, form fields, bulk class and id names. Whenever the structure follows a pattern, something like ul>li*6>a saves a dozen typed lines. The moment the structure stops being regular is the moment to stop typing abbreviations and write the tags directly, since Emmet accelerates markup, it does not replace understanding it. Sections cover basic HTML tags and attributes, common page structures such as headers, lists, tables and forms, CSS shorthands, and nesting with multiplication. Two habits matter while writing: the $ placeholder parks the cursor where a value belongs and repeated Tab jumps through them, and a hyphen inside a CSS abbreviation separates value groups, so m10-20 expands to a two-value margin rather than something you have to look up. Multiplication and numbering compose, so a table body, a nav bar or a form grid can be produced from one line and edited from there.
Typical Use Case
For front-end engineers who still type tags by hand while sketching a page skeleton or generating repeated structures. Emmet compresses intent into a short abbreviation that expands when you press Tab. Covers core HTML syntax (ids, classes, child with >, sibling with +, multiplication with *n, $ for auto-numbering, attributes), snippets such as form:post and btn:submit, and CSS shorthand for dimensions, spacing, colour, typography and flexbox alignment. Start with the difference between > and +.
HTML Basics 8
! or html:5div#appdiv.containerul>li*3ul>li.item$*3p>span^diva[href="#" title="link"]imgCommon HTML Structures 8
form:postinput:textinput:emailbtn:submitselect>option*3table>tr^tr>td*3lorem10lorem-cnCSS Shorthand 18
w100w100ph50m10m10-20p10-20-30bgc#333c#ffffz16fw700d:fd:gjc:cai:cpos:at0 r0 b0 l0bd1-s-#cccbr8Nesting & Loops 5
div>ul>li*5>a{Item $}div+p+bq{Hello}${Item}(#header>ul>li*2>a)+footer>pParameter matrix
| Parameter | Effect | Example |
|---|---|---|
! / html:5 | 展开为 HTML5 文档骨架,含 doctype、html/head/body | ! 或 html:5 |
div#app | 同时生成标签与 ID,这是最基础的组合 | div#app |
div.container | 生成带一个 class 的元素;class 可写多个用点分隔 | div.container |
ul>li*3 | > 是子级关系,直接嵌套在上一元素内 | ul>li*3 |
ul>li.item$*3 | *n 重复 n 次;$ 让类名随次数自增(item1/item2/item3) | ul>li.item$*3 |
p>span^div | ^ 回到上一级父元素插入兄弟,是构造多分支结构的必备操作符 | p>span^div |
a[href="#" title="link"] | 方括号写属性;双引号包裹含特殊字符的值更安全 | a[href="#" title="link"] |
img | 缩写标签名 img 直接展开为 img 标签;部分标签有更短别名 | img |
form:post | 冒号后是标签类型修饰,展开成带 method="post" 的 form | form:post |
input:text / input:email | 生成带 type 的 input;这是表单里最常用的一组 | input:email |
btn:submit | 展开成 type="submit" 的 button,btn 是 button 的缩写 | btn:submit |
select>option*3 | 快速搭出下拉框骨架;带值的写法是 option$ | select>option*3 |
table>tr^tr>td*3 | 用 ^ 换行构造表格:两个 tr 三个 td,注意按 Tab 展开时机 | table>tr^tr>td*3 |
lorem10 | 插入 10 词英文占位文本,用于验证排版与溢出 | lorem10 |
lorem-cn | 插入中文占位文本,验证中文字体与换行更真实 | lorem-cn |
w100 / h50 | width / height 的缩写,单位默认 px | w100 |
w100p | 加 p 后缀表示百分比,w100p 即 width: 100% | w100p |
m10 / m10-20 | margin 缩写;连字符分隔多值对应上下左右,m10-20 即纵向 10 横向 20 | m10-20 |
p10-20-30 | padding 三值写法对应上、左右、下 | p10-20-30 |
bgc#333 / c#fff | 背景色与文字色缩写;写 # 时可省略 #,部分配置里 c 有别的含义需确认 | bgc#333 |
fz16 / fw700 | font-size 与 font-weight 缩写;fw700 是常用字重写法 | fz16 |
d:f / d:g | display 缩写:flex 与 grid,是把布局切换成本降到最低的两条 | d:f |
jc:c / ai:c | justify-content 与 align-items 的缩写,用于 flex 居中(配合 d:f) | jc:c |
pos:a | position 缩写,a 即 absolute | pos:a |
t0 r0 b0 l0 | top/right/bottom/left 简写,四条一起写是绝对定位铺满的惯用写法 | t0 r0 b0 l0 |
bd1-s-#ccc | border 缩写:宽度-样式-颜色,展开为 border: 1px solid #ccc | bd1-s-#ccc |
br8 | border-radius: 8px;写 br50% 得圆角胶囊,是标签的常见形态 | br8 |
div>ul>li*5>a{Item $} | 大括号内是文本占位,$ 自增:a 的内容依次是 Item 1 到 Item 5 | div>ul>li*5>a{Item $} |
div+p+bq | + 是兄弟关系,三个元素同层平铺 | div+p+bq |
{Hello} | 纯文本占位,展开后作为可编辑文本出现在标签内容里 | {Hello} |
${Item} | 把 $ 放进文本里,实现「标签文本带序号」的展开结果 | ${Item} |
(#header>ul>li*2>a)+footer>p | 括号把一段结构分组,避免分组内所有标签与后续串成一条链 | (#header>ul>li*2>a)+footer>p |
Common pitfalls
Symptom展开出来的结构与预期不同,多了一层或少了一层嵌套。
Cause> 是子级、+ 是兄弟、^ 是回到父级;连写时三个符号混用极易读错。
Fix把长缩写拆成两段展开确认;对复杂结构用括号显式分组。
Symptom编号没有自增,所有重复项类名或文本完全一样。
Cause$ 必须放在类名、ID、属性值或文本里,纯标签名中的 $ 无效。
Fix写成 li.item$*3 或 a{Item $},$ 放在需要变化的位置。
Symptom按 Tab 没反应,缩写原样留在文件里。
Cause光标不在行尾、当前文件语言不是 HTML/CSS,或该编辑器未启用 Emmet。
Fix确认文件类型与 Tab 键行为;有些编辑器需要用 Ctrl+E 这类显式展开快捷键。
SymptomCSS 里 c#fff 展开成了预期之外的属性。
Cause不同编辑器/插件预设的 c 可能指 color,也可能指其它属性映射。
Fix展开后看一眼实际结果;不确定时直接写全属性名。
Symptom写完 `!` 展开出的是 XHTML 或旧版 doctype。
Cause不同插件对 `!` 的默认展开版本不一致,VS Code 系通常带 html:5。
Fix显式写 html:5 而不是只写 `!`。
Symptom在 JS/TS 文件里写 HTML 缩写,展开成了 JSX 但结构不对。
Cause同一份缩写在 HTML 与 JSX 上下文里的处理规则不同(自闭合标签、属性名大小写)。
Fix在 JSX 里显式写 JSX 语法,尤其是自闭合标签与 className。
Symptom生成的表格只有一个 td 或 tr 结构错乱。
Causetable 简写需要按 Tab 时机分两步展开,一步到位会把结构压平。
Fix分两次触发展开:先展开 tr 层级,再展开 td 层级。
Symptom展开结果里 class 属性没写上,但缩写里明明写了点号。
Cause缩写被当作文本(前置转义)导致解析中断,或所在位置在注释/字符串里。
Fix把缩写移到标签内容的正常位置重新输入,避免插在字符串与注释中间。
Troubleshooting
1确认编辑器是否启用了 Emmet 展开
grep -rn "emmet" .vscode/settings.json未配置时展开键与语言绑定可能都不是预期值。
2在 CSS 里做一次最小验证
grep -rn "d:f\|jc:c" src --include="*.vue"确认简写已按预期落成 display:flex 与 justify-content:center。
3排查模板里是否有大量手写重复结构
grep -c "<div class=" pages/index.vue重复度高说明该处适合用组件或循环,而不是继续手写。
4确认项目中缩写生成的结构与既有风格一致
grep -rn "lorem" src占位文本残留在提交里是很常见的事故。
5检查 JSX 上下文里的自闭合标签写法
grep -rn "<img[^>]*/>" src非自闭合写法在 JSX 里会直接编译失败。
6确认编号类名没有与既有样式重复
grep -rn "item1\|item2\|item3" src --include="*.css"缩写生成的类名若恰好撞上已有类名,样式会互相污染。
Command Examples
CSS abbreviations: two properties, units, and shorthand values
m10-20
p10-20-30
bd1-s-#ccc
br8
d:f jc:c ai:cHyphen-separated segments expand to top/right/bottom/left: two values mean vertical plus horizontal, three mean top + horizontal + bottom, and only four cover all sides. Units may be omitted and default to px, and a trailing # supplies the colour. This is the fastest way to type repetitive declarations, but the emitted CSS usually needs a manual cleanup pass.
Output
m10-20 → margin: 10px 20px; p10-20-30 → padding: 10px 20px 30px; bd1-s-#ccc → border: 1px solid #ccc; br8 → border-radius: 8px;
HTML structure: multiplication, sibling climb, and grouping
ul>li.item$*3
p>span^div
table>tr^tr>td*3
(#header>ul>li*2>a)+footer>p> is child, + is sibling, and ^ climbs one level, which together remove the need for the mouse. $ produces incrementing numbers under multiplication (item$*3 gives item1/item2/item3), while a bare $ counts up from 100 — the one symbol that is safer to type inside braces before pressing Tab: div>ul>li*5>a{Item $}.
Output
ul>li.item$*3 → <ul><li class="item1"></li>…</ul> p>span^div → <p><span></span></p><div></div>
Attribute and snippet abbreviations: a[href] and input:text
a[href="#" title="link"]
form:post
input:email
btn:submit
img
select>option*3Brackets hold key/value pairs and a colon selects an element variant: form:post expands to a form with method="post", and input:email and btn:submit are built-in snippets that fill in the required type as well. Snippet names come from a built-in list and your editor autocompletes them, so read the suggestion rather than memorizing the catalogue.
Output
a[href="#" title="link"] → <a href="#" title="link"></a> input:email → <input type="email"> btn:submit → <button type="submit"></button>
Placeholder text with lorem and the document skeleton
lorem10
lorem-cn
!lorem10 drops ten words inside a tag and beats typing lorem ipsum by hand for layout placeholders; lorem-cn requires a separate Chinese plugin and simply will not expand without it, so swap in real copy rather than shipping placeholder text. ! expands the HTML5 skeleton, giving a new document a working starting point.
Output
lorem10 → Lorem ipsum dolor sit amet consectetur adipiscing elit… ! → <!DOCTYPE html> + html/head/body 完整骨架
Common Pitfalls
- Structural abbreviations produce HTML that is usable, not correct: ul>li*3 ships no text, div+p leaves empty containers, and btn:submit means nothing outside a form. Fill in content and semantic tags after expanding, or screen readers will announce a run of empty elements.
- The $ in li.item$*3 is substituted with a number at expansion time. Typing a real dollar sign, or an SCSS variable name like $primary, inside an Emmet-enabled region can be swallowed or mis-expanded. Comment out or break up such names when typing Sass variables.
- Emmet parses continuously with whatever you type, so fragments inside a class name such as col-md-6 may trigger an unexpected expansion, especially when pasting third-party code. Disable Emmet before bulk pasting external CSS or HTML, then expand deliberately afterwards.
- br8 and a .br selector are entirely different targets: br is border-radius in CSS while br in an HTML region is the line-break tag. The same two characters expand differently depending on where the cursor is, so confirm the current region before expanding.
- lorem10 and lorem-cn output is layout filler, not shippable content, and lorem-cn depends on a third-party plugin that may leave the text unexpanded. Before publishing, search globally for lorem and for $ artifacts such as item1 or item2.
- Counts in abbreviations are matched literally: td*3 makes three cells, div*3 makes three divs, and a typo like td*30 silently produces thirty elements that are hard to spot in a large table. Check the row count with git diff after expanding.
Tips
- VS Code ships with Emmet built in — press Tab to expand abbreviations in HTML, CSS, JSX and Pug files.
- $ is an auto-incrementing placeholder; $$ zero-pads (01, 02) and $@- reverses the order.
- CSS shorthands join multiple values with a hyphen, e.g. m10-20 expands to margin: 10px 20px.
FAQ
What is the difference between lorem10 and lorem-cn?
lorem10 emits ten words of Latin-style filler, and the trailing number sets the length directly, so you can stretch or shrink the placeholder to an exact size. lorem-cn produces Chinese filler, which matches the shape and word rhythm of a real Chinese interface mockup — but it depends on plugin support and is not available everywhere by default. Both simply inject text into element content, so they belong on p, div or span. If the block itself needs to repeat, multiply it: lorem*3.
What problem do parentheses solve in an abbreviation, and how do I use them?
Long abbreviations get hard to read because scope becomes guesswork, and parentheses let you fence off sections that parse independently. A representative form is (#header>ul>li*2>a)+footer>p: the parenthesised part builds the ID-bearing header structure, and the trailing +footer>p attaches the footer as its sibling. Without the grouping you have to remember how far the # reaches and count the closing ^ symbols by hand. Fenced, each chunk can be verified on its own, which makes long skeletons far more predictable.
How do I give one tag both an href and a title in a single abbreviation?
Wrap the attributes in square brackets and separate them with spaces: a[href="#" title="link"] expands into an anchor carrying both attributes. Always quote values with double quotes — that is what keeps the parser honest when the value itself contains spaces or symbols. Unquoted values break as soon as they do. You can also mix shorthand forms for class and id alongside explicit attributes, but keep in mind that attribute shorthand and {} text interpolation are separate mechanisms: do not expect a brace expression inside the bracket to evaluate.
What do {Hello} and ${Item} each expand to?
{Hello} is plain text interpolation — the braced content lands verbatim in the element text position with no numbering involved. ${Item} adds an incrementing counter: inside a multiplication or list structure the number follows its position, producing Item 1, Item 2, Item 3. The digits come from the $ placeholder used inside the text interpolation, and a $@- variant generates the same sequence in reverse. Reach for {} when you want fixed placeholder copy, and for ${} only when you need a run of numbered items.
What exactly do form:post, input:email and btn:submit fill in for me?
Each one is a common tag pre-loaded with the attribute people most often forget. form:post yields a form carrying method="post". input:email produces <input type="email"> and input:text produces <input type="text">, and the type attribute is what lets the browser apply email-format validation and pick the right mobile keyboard. btn:submit gives <button type="submit"></button>; buttons default to submit anyway, so writing it out matters mainly in files full of type="button" buttons where an accidental submit would bite. Using this family repeatedly across a form is far quicker than typing full tags.
Official References
Each command links to its official documentation below, so you can verify the latest usage and read deeper.
Maintained by LaoHand
Publicly updated on Jul 21, 2026, continuously proofread against official docs.
Contact Us
Wrong command or description? Send us corrections, business inquiries or product feedback by email.
Contact Us