Emmet Editor Plugin for Dynamic HTML/CSS Snippets
By Mark Volkmann, OCI Partner and Principal Software Engineer
March 2018
Overview
Emmet is an editor plugin for quickly entering HTML, XML, and CSS. It also supports many "actions" that operate on HTML and XML elements. The most commonly used action is to expand an abbreviation or snippet.
Emmet was created by Sergey Chikuyonok. The original name was "Zen Coding."
Emmet is available for many editors including Atom, Eclipse, Emacs, Notepad++, Sublime, Vim, Visual Studio (VS) Code, and WebStorm. However, some implementations do not support all the defined snippets and actions.
Emmet is not just a simple snippet manager. It parses entered text to extract meaning. These kinds of snippets are referred to as "dynamic snippets."
We will see many examples later, but here's one. The snippet div#some-id.class1.class2[attr1=one attr2=2]{some content}
expands to <div id="some-id" class="class1 class2" attr1="one" attr2="2">some content</div>
. Amazing!
Simpler snippets are also very useful. For example, the CSS snippet mb10
expands to margin-bottom: 10px;
.
The main web site for Emmet is https://emmet.io/, and you'll find a handy cheat sheet at https://docs.emmet.io/cheat-sheet/.
Getting Started
You will need to configure Emmet within your editor/IDE of choice. Instructions for specific ones can be found at https://emmet.io/download/. Click the box for your editor to see the details.
Rather than walk through the steps for every editor, this article covers just two. Currently VS Code seems to be the most popular editor, so that is covered. I use Vim, so that is also covered.
Instructions for other popular editors can be found at the following sites:
- Atom: https://atom.io/packages/emmet
- IntelliJ: https://www.jetbrains.com/help/idea/enabling-emmet-support.html
- Notepad++: https://github.com/emmetio/npp/#readme
- Sublime: https://github.com/sergeche/emmet-sublime#readme
- Webstorm: https://www.jetbrains.com/help/webstorm/enabling-emmet-support.html
VS Code
Details on configuring Emmet for VS Code can be found at https://code.visualstudio.com/docs/editor/emmet. VS Code includes Emmet by default, enabled for these file types: css, haml, html, jade, jsx, less, sass, scss, slim, stylus, xml, and xsl. More file types can be added.
Configuring Emmet in VS Code
- Open Preferences ... Settings from the "File" menu in Windows and Linux, or the "Code" menu in macOS.
- Enter "Emmet" in the "Search Settings" input at the top.
- Note the available settings and their defaults on the left.
- Change settings in "USER SETTINGS" on the right.
- To enable use in React components in
.js
files, change the "emmet.includeLanguages" object to includejavascript: 'javascriptreact'
.
Using Emmet in VS Code
Suggestions are displayed as snippets as typed, along with non-Emmet suggestions.
To use the top suggestion before the snippet is fully entered, press enter or tab. To use a different suggestion, use to the up and down arrows keys to navigate to it and press enter or tab.
The expansion for the highlighted Emmet suggestion is displayed in a "documentation fly-out" to the right of the suggestion, so you know what will be inserted before you select it.
Some expansions contain insertion points, which are locations where additional text can be entered. The cursor will automatically be moved to an insertion point.
For example, when div
is expanded, the cursor is moved to the |
in <div>|</div>
.
For snippets with multiple insertion points, after entering a value in one, you can press tab to jump to the next one.
Vim Emulation in VS Code
In case you are interested in enabling Vim emulation in VS Code, here are the steps.
- Select View ... Extensions.
- Enter "vscodevim" in the search input.
- Press the "Install" button for the vscodevim extension.
To configure Vim emulation
- Select Code ... Preferences ... Settings.
- Enter "vim" in the "Search Settings" input at the top.
- See the available settings and their defaults on the left.
- Change settings in "USER SETTINGS" on the right.
Vim
The Emmet plugin for Vim is available at https://github.com/mattn/emmet-vim. Instructions for installing it using a variety of Vim plugin managers can be found there, as well as configuration details.
Configuration is accomplished by modifying your .vimrc
file.
All keyboard shortcuts for Emmet commands begin with . By default this is ctrl-y.
The most commonly used keyboard shortcut expands a snippet. The key sequence that triggers this is followed by a comma.
To change the value of , set the variable
g:user_emmet_leader_key
.
For example, to change it to the space key, add the following:
let g:user_emmet_leader_key='<space>'
Once these changes are made, Emmet expansions can be triggered by entering a snippet and pressing space followed by a comma while still in insert mode.
For snippets with more than one insertion point press <emmet-leader>n
to move to next one and <emmet-leader>N
to move to previous one.
By default Emmet snippets can be expanded in all file types. To restrict usage to specific file types, add the following.
let g:user_emmet_install_global = 0 " don't enable for all file types
autocmd FileType html,css,scss EmmetInstall " specifies file types
To use Emmet in .js or .jsx files that define React components, add the following.
let g:user_emmet_settings = {'javascript.jsx': {'extends': 'jsx'}}
autocmd FileType html,css,javascript.jsx,scss EmmetInstall
Syntax for HTML Snippets
The syntax for specifying HTML snippets is mostly like CSS selector syntax with no spaces.
In the examples that follow, the cursor position after triggering the snippet is indicated using the |
character.
Child elements are specified with the >
character.
For example, foo>bar>baz
expands to:
<foo>
<bar>
<baz>|</baz>
</bar>
</foo>
Sibling elements are specified with the +
character.
For example, foo+bar+baz
expands to:
<foo>|</foo>
<bar></bar>
<baz></baz>
Climb up the element hierarchy within a snippet using the ^
character. This adds a sibling to the parent of the last element that was generated.
For example, table>tr>th+th^tr>td+td
expands to:
<table>
<tr>
<th></th>
<th></th>
</tr>
<tr>
<td></td>
<td></td>
</tr>
</table>
The same result can be achieved using parentheses instead of ^
.
The equivalent snippet is table>(tr>th+th)+(tr>td+td)
. Perhaps this is easier to understand.
Even easier would be to enter this as multiple snippets rather than trying to reason about how to use just one.
Multiple ^
characters can be used to climb up multiple levels, but that results in snippets that are difficult to understand at a glance.
CSS class names are specified with the .
character.
For example, div.my-class
expands to:
<div class="my-class">|</div>
and div.c1.c2
expands to:
<div class="c1 c2">|</div>
Element ids are specified with the #
character.
For example, div#my-id
expands to:
<div id="my-id">|</div>
Attributes are specified between square brackets.
Values with no special characters do not require quotes. If special characters are present, enclose attribute values in single or double quotes.
For example, div[foo=1 bar=two]
expands to:
<div foo="1" bar="two">|</div>
and div[foo="contains space" bar='single quotes']
expands to
<div foo="contains space" bar="single quotes"></div>
Note that no commas are used between the listed attributes.
Element content is specified between curly braces.
For example, div{my content}
expands to:
<div>my content|</div>
Elements in a snippet can be repeated with the *
character followed by a number.
For example, td*3
expands to:
<td>|</td>
<td></td>
<td></td>
Incrementing numbers can be added in repeated content with the $
character. This can be used for ids, classes, and content.
For example, ul>li.item$*3
expands to:
<ul>
<li class="item1">|</li>
<li class="item2"></li>
<li class="item3"></li>
</ul>
Numbering starts at 1 by default. A different starting value can be specified with @start
and *times
.
For example, div{item $@4}*3
expands to:
<div>item 4|</div>
<div>item 5</div>
<div>item 6</div>
The syntax described above can be combined to create more powerful snippets.
For example, div#my-id.my-class[foo=1 bar=two]{my content}
expands to:
<div id="my-id" class="my-class" foo="1" bar="two">my content|</div>
Parts of snippets can be grouped using parentheses. This is useful for repeating specific sections.
For example, table>(thead>tr>th*3)+(tbody>(tr>td*3)*2)
expands to:
<table>
<thead>
<tr>
<th>|</th>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
<tr>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
</tr>
</tbody>
</table>
Emmet can sometimes guess desired tag names based on context. These are called "implicit tag names."
For example, .foo
expands to:
<div class="foo">|</div>
and ul>.foo
expands to:
<ul>
<li class="foo">|</li>
</ul>
Lorem Ipsum Text
"Lorem Ipsum" is scrambled Latin text that is frequently used as a placeholder for text that will be supplied later. Emmet can generate this text. By default it generates 100 words, but the number of desired words can be specified.
The snippet is the word "lorem" or the word "lipsum," optionally followed by a number.
For example, lorem
and lipsum
expand to 100 words, while lorem3
and lipsum3
expand to 3 words.
The words selected are random, but here is an example:
Sit debitis aliquam.
HTML Snippets
Emmet supports a large number of HTML snippets. The ones shown below seem to be the most useful.
!
expands to a common HTML template.
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <title></title>
- </head>
- <body>
- |
- </body>
- </html>
a
expands to<a href="|"></a>
a:link
expands to<a href="http://|"></a>
a:mail
expands to<a href="mailto:|"></a>
btn
orbutton
expands to<button>|</button>
c
expands to<!-- | -->
img
expands to<img src="|" alt="">
input:{type}
- type can be one of button, checkbox, color, date, datetime, datetime-local, email, file, hidden, image, month, number, password, radio, range, search, submit, tel, text, time, url, or week
- ex:
input:number
expands to<input id="" type="number" name="">
label
expands to<label for="|"></label>
link
expands to<link rel="stylesheet" href="|">
link:favicon
expands to<link rel="shortcut icon" type="image/x-icon" href="|favicon.ico">
ol+
is an abbreviation for the snippetol>li
opt
oroption
expands to<option value="|"></option>
select+
is an abbreviation for the snippetselect>option
script:src
expands to<script src="|"></script>
table+
is an abbreviation for the snippettable>tr>td
tarea
ortextarea
expands to<textarea id="|" name="" cols="30" rows="10"></textarea>
tr+
is an abbreviation for the snippettr>td
ul+
is an abbreviation for the snippetul>li
CSS Snippets
Emmet supports a large number of CSS snippets. The ones show below seem to be the most useful.
It may seem that there are too many to remember. However, in most cases your first guess for what a given snippet would be is correct.
ac
expands toalign-content: |;
ac:c
expands toalign-content: center;
ac:fe
expands toalign-content: flex-end;
ac:fs
expands toalign-content: flex-start;
ac:s
expands toalign-content: stretch;
ac:sa
expands toalign-content: space-around;
ac:sb
expands toalign-content: space-between;
ai
expands toalign-items: |;
ai:b
expands toalign-items: baseline;
ai:c
expands toalign-items: center;
ai:fe
expands toalign-items: flex-end;
ai:fs
expands toalign-items: flex-start;
ai:s
expands toalign-items: stretch;
as
expands toalign-self: |;
as:b
expands toalign-self: baseline;
as:c
expands toalign-self: center;
as:fe
expands toalign-self: flex-end;
as:fs
expands toalign-self: flex-start;
as:s
expands toalign-self: stretch;
b
expands tobottom: |;
bd
expands toborder: |;
bd:n
expands toborder: none;
bdb
orbb
expands toborder-bottom: |;
bdl
orbl
expands toborder-left: |;
bdr
orbr
expands toborder-right: |;
bdt
orbt
expands toborder-top: |;
bg
expands tobackground: #000;
bgc
expands tobackground-color: #fff;
bgc:t
expands tobackground-color: transparent;
c
expands tocolor: #000;
cur:d
expands tocursor: default;
cur:p
expands tocursor: pointer;
d:b
ord
expands todisplay: block;
d:f
expands todisplay: flex;
d:g
does not givedisplay: grid
;d:i
expands todisplay: inline;
d:ib
expands todisplay: inline-block;
d:li
expands todisplay: list-item;
d:n
expands todisplay: none;
d:t
expands todisplay: table;
fxd
expands toflex-direction: |;
fxd:c
expands toflex-direction: column;
fxd:r
expands toflex-direction: row;
ff
expands tofont-family: |;
ff:m
expands tofont-family: monospace;
ff:s
expands tofont-family: serif;
ff:ss
expands tofont-family: sans-serif;
fs
expands tofont-style: |;
fs:i
expands tofont-style: italic;
fs:n
expands tofont-style: normal;
fw
expands tofont-weight: |;
fw:b
expands tofont-weight: bold;
fw:n
expands tofont-weight: normal;
fz
expands tofont-size: |;
h
expands toheight: |;
jc
expands tojustify-content: |;
jc:c
expands tojustify-content: center;
jc:fe
expands tojustify-content: flex-end;
jc:fs
expands tojustify-content: flex-start;
jc:sa
expands tojustify-content: space-around;
jc:sb
expands tojustify-content: space-between;
l
expands toleft: |;
lh
expands toline-height: |;
m
expands tomargin: |;
mb
expands tomargin-bottom: |;
ml
expands tomargin-left: |;
mr
expands tomargin-right: |;
mt
expands tomargin-top: |;
o
expands tooutline: |;
p
expands topadding: |;
pb
expands topadding-bottom: |;
pl
expands topadding-left: |;
pr
expands topadding-right: |;
pt
expands topadding-top: |;
r
expands toright: |;
t
expands totop: |;
ta:c
expands totext-align: center;
ta:j
expands totext-align: justify;
ta:l
orta
expands totext-align: left;
ta:r
expands totext-align: right;
td:l
expands totext-decoration: line-through;
td:n
ortd
expands totext-decoration: none;
td:u
expands totext-decoration: underline;
tt:c
expands totext-transform: capitalize;
tt:l
expands totext-transform: lowercase;
tt:u
ortt
expands totext-transform: uppercase;
v:h
orv
expands tovisibility: hidden;
v:v
expands tovisibility: visible;
va:b
expands tovertical-align: bottom;
va:m
expands tovertical-align: middle;
va:t
orva
expands tovertical-align: top;
w
expands towidth: |;
z
expands toz-index: |;
@media
or@m
expands to@media screen { | }
A number can be added after many CSS snippets to specify a value. These include snippets for border, font, margin, and padding.
For example, m20
expands to margin: 20px;
.
Actions
The tables below describe Emmet actions and the keys to trigger them in VS Code and Vim. For Windows and Linux, substitute "ctrl" wherever you see "cmd."
In VS Code, all Emmet actions can be selected from the "Command Pallete" which is opened by pressing cmd-P. None of these commands have a default keybinding.
To add keybindings in VS Code:
- Open Preferences ... Keyboard Shortcuts from the "File" menu in Windows and Linux, or the "Code" menu in macOS.
- Enter "Emmet" in the search input at the top to filter the commands to just those supplied by Emmet.
- Select a command and press the "+" that appears to its left.
- Finally, type the shortcut key sequence to be associated with the command and press enter.
VS Code allows keybindings to be added to commands even if the keybinding is already assigned to another command. To determine if a keybinding has been assigned to multiple commands, right-click any command that uses it and select "Show Conflicts."
In the tables below, the "VS Code Key" column shows suggested shortcut keys, but none of these are configured by default.
Commonly Used Actions
Action | Description | VS Code Key | Vim Key |
---|---|---|---|
expand abbreviation | the primary action | enter or tab | <emmet-leader> comma in insert mode |
go to next edit point | jumps to next edit point | cmd-opt-right arrow | <emmet-leader> n |
go to previous edit point | jumps to previous edit point | cmd-opt-left arrow | <emmet-leader> N |
wrap with abbreviation | wraps selected text in a snippet for which you will prompted | select lines and cmd-A | <emmet-leader> comma in visual mode |
balance tag outward | selects all of element under cursor; repeat to expand outward | cmd-d | <emmet-leader> d |
balance tag inward | selects all of element under cursor, but one level less than current selection; repeat to expand inward | cmd-D | <emmet-leader> D, but doesn't work |
remove tag | deletes tag under cursor, but not its contents | cmd-k | <emmet-leader> k (incorrectly also deletes contents) |
toggle comment | toggles whether the tag under the cursor is commented out | cmd-/ | <emmet-leader> / |
merge lines | merges selected lines into one line | cmd-M | <emmet-leader> m |
split/join tag | toggles tag under cursor from having a closing tag to closing in shorthand way (deletes content) | cmd-j | <emmet-leader> j |
go to matching pair | jumps between a start and end tag | cmd-T | not supported |
select next item | moves to next start tag, attribute name, or attribute value and selects it | cmd-> | not supported |
select previous item | moves to previous start tag, attribute name, or attribute value and selects it | cmd-< | not supported |
increment number by 1 | adds to number under cursor | ctrl-up arrow | not supported |
decrement number by 1 | subtracts from number under cursor | ctrl-down arrow | not supported |
increment number by 10 | adds to number under cursor | ctrl-shift-up arrow | not supported |
decrement number by 10 | subtracts from number under cursor | ctrl-shift-down arrow | not supported |
increment number by .1 | adds to number under cursor | ctrl-opt-up arrow | not supported |
decrement number by .1 | subtracts from number under cursor | ctrl-opt-down arrow | not supported |
Less Commonly Used Actions
Action | Description | VS Code Key | Vim Key |
---|---|---|---|
evaluate math expression | replaces the math expression under cursor with result | cmd-Y | not supported |
encode/decode image to data:URL | toggles CSS url function value between a file path and a data: URL | cmd-I | not supported |
reflect CSS value | copies CSS value under cursor to all vendor-prefixed variations in same rule | cmd-b | not supported |
update image size | adds width and height attributes to the img tag under cursor | cmd-U | <emmet-leader> i, but doesn't work |
Non-standard Actions
These are actions that are not described at https://docs.emmet.io but are implemented by either VS Code or vim-emmet.
Action | Description | VS Code Key | Vim Key |
---|---|---|---|
update tag | changes tag under cursor; will prompt for new tag | cmd-c | not supported |
anchorize URL | changes URL under cursor to an anchor tag using that URL; must start with http:// or https:// | not supported | <emmet-leader> a in insert mode |
"split/join tag" example
With the cursor over the start tag of the element foo, this would change <foo><bar>baz</bar></foo>
to <foo />
.
Custom snippets
Many Emmet plugins support user-defined custom snippets. For more information about these, see https://docs.emmet.io/customization/.
Summary
Emmet can save web developers a lot of time. Once you learn the basic syntax, it's pretty easy to use.
Give it a try in your favorite editor!
Software Engineering Tech Trends (SETT) is a regular publication featuring emerging trends in software engineering.