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 | Expands to the HTML5 document skeleton with doctype, html/head/body. | ! or html:5 |
div#app | Generates the tag and the ID together, the most basic combination. | div#app |
div.container | Generates an element with one class; multiple classes are separated by dots. | div.container |
ul>li*3 | > is the child relationship, nesting directly inside the previous element. | ul>li*3 |
ul>li.item$*3 | *n repeats n times; $ increments the class name per iteration (item1/item2/item3). | ul>li.item$*3 |
p>span^div | ^ goes back up one parent level to insert a sibling, essential for branching structures. | p>span^div |
a[href="#" title="link"] | Attributes go in square brackets; wrapping values with special characters in double quotes is safer. | a[href="#" title="link"] |
img | The abbreviation img expands directly to an img tag; some tags have shorter aliases. | img |
form:post | The modifier after the colon expands to a form with method="post". | form:post |
input:text / input:email | Generates an input with a type; the most commonly used set in forms. | input:email |
btn:submit | Expands to a button with type="submit"; btn is the abbreviation for button. | btn:submit |
select>option*3 | Quickly builds a dropdown skeleton; the value-carrying form is option$. | select>option*3 |
table>tr^tr>td*3 | Builds a table with ^ line breaks: two tr and three td—mind the Tab timing. | table>tr^tr>td*3 |
lorem10 | Inserts 10 words of English placeholder text, useful for checking layout and overflow. | lorem10 |
lorem-cn | Inserts Chinese placeholder text, for more realistic Chinese font and line-break testing. | lorem-cn |
w100 / h50 | Abbreviations for width / height; unit defaults to px. | w100 |
w100p | The p suffix means percent, so w100p is width: 100%. | w100p |
m10 / m10-20 | margin abbreviation; hyphen-separated values map to top/right/bottom/left, so m10-20 is 10 vertical and 20 horizontal. | m10-20 |
p10-20-30 | The three-value padding form maps to top, left/right, bottom. | p10-20-30 |
bgc#333 / c#fff | Background-color and text-color abbreviations; the # may be omitted, but in some configs c has another meaning—verify it. | bgc#333 |
fz16 / fw700 | font-size and font-weight abbreviations; fw700 is the common weight form. | fz16 |
d:f / d:g | display abbreviations: flex and grid, the two that minimize the cost of switching layouts. | d:f |
jc:c / ai:c | Abbreviations for justify-content and align-items, used for flex centering (with d:f). | jc:c |
pos:a | position abbreviation; a is absolute. | pos:a |
t0 r0 b0 l0 | top/right/bottom/left shorthand; writing all four is the idiom for a full-bleed absolutely positioned element. | t0 r0 b0 l0 |
bd1-s-#ccc | border abbreviation—width-style-color—expands to border: 1px solid #ccc. | bd1-s-#ccc |
br8 | border-radius: 8px; writing br50% gives a pill shape, a common tag style. | br8 |
div>ul>li*5>a{Item $} | Curly braces hold a text placeholder and $ increments: the content of the a elements runs from Item 1 to Item 5. | div>ul>li*5>a{Item $} |
div+p+bq | + is the sibling relationship; the three elements are laid out at the same level. | div+p+bq |
{Hello} | A pure text placeholder that appears as editable text inside the tag content. | {Hello} |
${Item} | Puts $ inside the text to produce expansion with numbered tag text. | ${Item} |
(#header>ul>li*2>a)+footer>p | Parentheses group a chunk of structure so that not every tag inside chains with what follows. | (#header>ul>li*2>a)+footer>p |
Common pitfalls
SymptomThe expanded structure differs from what you expected, one nesting level too many or too few.
Cause> is a child, + is a sibling, ^ goes back to the parent; mixing all three in one chain is very easy to misread.
FixSplit long abbreviations and expand them in two steps to verify; use parentheses to group explicitly for complex structures.
SymptomThe numbering does not increment; all repeated items end up with identical class names or text.
Cause$ must appear in a class name, ID, attribute value, or text—a bare $ in a tag name does nothing.
FixWrite li.item$*3 or a{Item $}, placing $ where you want the value to vary.
SymptomPressing Tab does nothing and the abbreviation stays in the file as-is.
CauseThe cursor is not at the end of the line, the file language is not HTML/CSS, or Emmet is not enabled in that editor.
FixConfirm the file type and Tab key behavior; some editors need an explicit expansion shortcut like Ctrl+E.
SymptomIn CSS, c#fff expands into an unexpected property.
CauseDepending on the editor/plugin preset, c may mean color or some other property mapping.
FixLook at the actual result after expanding; write the full property name when unsure.
SymptomTyping ! expands into XHTML or an old doctype.
CauseDifferent plugins default ! to different versions; the VS Code family usually maps it to html:5.
FixWrite html:5 explicitly instead of just !.
SymptomWriting an HTML abbreviation inside a JS/TS file expands to JSX but with the wrong structure.
CauseThe same abbreviation is handled differently in HTML and JSX contexts (self-closing tags, attribute-name casing).
FixWrite explicit JSX syntax inside JSX, especially for self-closing tags and className.
SymptomThe generated table has only a single td, or its tr structure is malformed.
CauseThe table abbreviation needs to be expanded in two steps at the right Tab moments; doing it in one shot flattens the structure.
FixTrigger expansion twice: first at the tr level, then at the td level.
SymptomThe expanded result is missing the class attribute even though you clearly wrote dots in the abbreviation.
CauseThe abbreviation was treated as text (leading escape), interrupting parsing, or it sits inside a comment/string.
FixRetype the abbreviation at a normal position in the tag content, avoiding strings and comments.
Troubleshooting
1Confirm whether the editor has Emmet expansion enabled.
grep -rn "emmet" .vscode/settings.jsonWhen unconfigured, the expansion key and language bindings may both differ from the expected values.
2Do a minimal check in CSS.
grep -rn "d:f\|jc:c" src --include="*.vue"Confirm the shorthand produced display:flex and justify-content:center as expected.
3Check whether the template has a lot of hand-written repeated structure.
grep -c "<div class=" pages/index.vueHeavy repetition means that spot suits a component or a loop rather than more hand-writing.
4Confirm the structures generated by abbreviations match the existing style.
grep -rn "lorem" srcPlaceholder text left in a commit is a very common accident.
5Check self-closing tag syntax in JSX contexts.
grep -rn "<img[^>]*/>" srcA non-self-closing form fails to compile in JSX.
6Confirm numbered class names do not collide with existing styles.
grep -rn "item1\|item2\|item3" src --include="*.css"If a class name generated by an abbreviation happens to match an existing one, the styles pollute each other.
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> + full html/head/body skeleton
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