
体育外围网
Earlier this year, I shared the
HTML boilerplate
[2]
I like to use when starting new web projects with line-by-line explanations on my blog. It’s a collection of mostly
tags and attributes I usually use on every website I build. Until recently, I would just copy and paste the boilerplate whenever I needed it, but I’ve decided to improve my workflow by adding it as a snippet to
VS Code
[3]
— the editor of my choice.
Snippets And Abbreviations In Visual Studio Code
VS Code comes built-in with custom user snippets [4] and HTML and CSS snippets and abbreviations [5] provided by Emmet [6] .
For example, if you type
p>a{Sign Up}
in an HTML document and press
Enter
or
Tab
, Emmet will turn it into the following markup:
Note : Visit the Emmet docs [7] to learn how to use the abbreviation syntax [8] .
If we need this specific abbreviation regularly, we can save it as a snippet to improve our workflow even more.
{ "html": { "snippets": { "signup": "p>a{Sign Up}" } } }
Now we can type
signup
and press
Enter
or
Tab
and we’ll get the same result. I’ll explain how to create snippets in the
next section
[9]
.
Emmet comes with
a bunch of HTML snippets
[10]
by default. For example,
!
creates the basic structure of an HTML document.
Document
That’s great, but if we want to adapt this snippet by removing or adding elements and attributes, we have to overwrite it and create our own snippet.
Creating And Overwriting Snippets
If we want to create our own Emmet snippets or overwrite existing ones in VS Code, the following steps are necessary:
-
Create a
snippets.json
file, add this basic JSON structure and save it somewhere on your hard disk.
{ "html": { "snippets": { } }, "css": { "snippets": { } } }
-
Open the VS Code settings (Code → Preferences → Settings) and search for “Emmet Extensions Path”.
-
Click “Add Item”, enter the path to the folder where you’ve saved the
snippets.json
file you’ve created earlier and press “OK”.
That’s it. Now we’re ready to create snippets by adding properties to the
html
and
css
objects where the
key
is the name of the snippet and the
value
an abbreviation or a string.
Some Of My Custom HTML Snippets
Before we dive deep into snippet creation and I show you how I created a snippet for my HTML boilerplate, let’s warm up first with some small, but useful snippets I’ve created, as well.
Lazy Loading
Out of the box, there’s an
img
abbreviation, but there’s none for lazily loaded images. We can use the default abbreviation and just add the additional attributes and attribute values we need in square brackets.
{ "html": { "snippets": { "img:l": "img[width height loading='lazy']" } } }
img:l
+
Enter
/
Tab
now creates the following markup:
Page
Most pages I create consist of
,
and
landmarks and an
. The custom
page
abbreviation lets me create that structure quickly.
"snippets": { "page": "header>h1^main+footer{${0:©}}" }
page
+
Enter
/
Tab
creates the following markup:
That abbreviation is quite long, so let’s break it down into smaller bits.
Breakdown
Create an
element and a child
.
header>h1
Move up, back to the level of the
, and create a
that follows
.
^main+footer
Set the final tab stop within the
and set the default text to
©
.
{${0:©}}
Navigation
The abbreviation
nav
just creates a
start and end tag by default, but what I usually need is a
with a nested
,
elements and links (
). If there are multiple
elements on a page, they should also be labeled, for example by using
aria-label
.
"nav": "nav[aria-label='${1:Main}']>ul>(li>a[aria-current='page']{${2:Current Page}})+(li*3>a{${0:Another Page}})"
That looks wild, so let’s break it down again.
Breakdown
We start with a
element with an
aria-label
attribute and a nested
.
${1:Main}
populates the attribute with the text “Main” and creates a tab stop at the attribute value by moving the cursor to it and highlighting it upon creation.
nav[aria-label='${1:Main}']>ul
Then we create four list items with nested links. The first item is special because it marks the active page using
aria-current="page"
. We create another tab stop and populate the link with the text “Current Page”.
(li>a[aria-current='page']>{${2:Current Page}})
Finally, we add three more list items with links and the link text “Another page”.
(li*3>a>{${0:Another Page}})
Before our adaptations, we got this:
<-- Before: nav + TAB/Enter -->
Now we get this:
<-- After: nav + TAB/Enter -->
Style
The default
style
abbreviation only creates the
start and end tag, but usually when I use the
element I do it because I quickly want to test or debug something.
Let’s add some default rules to the
tag:
"style": "style>{\* { box-sizing: border-box; \}}+{n${1:*}:focus \{${2: outline: 2px solid red; }\} }+{n
"style": "style>{\* { box-sizing: border-box; \}}+{n${1:*}:focus \{${2: outline: 2px solid red; }\} }+{n${0}}"
}"
Breakdown
Some characters (e.g.
$
,
*
,
{
or
}
) have to be escaped using
\
.
style>{\* { box-sizing: border-box; \}}
n
creates a linebreak and
${1:*}
places the first tab stop at the selector
*
.
{n${1:*}:focus \{${2: outline: 2px solid red; }\}}
Alright, enough warming-up. Let’s create complex snippets. At first, I wanted to create a single snippet for my boilerplate, but I created three abbreviations that serve different needs.
Boilerplate Small
This is a boilerplate for quick demos, it creates the following:
- Basic site structure,
-
viewport
meta tag, - Page title,
-
-
A
{ "!": "{}+html[lang=${lang}]>(head>meta:utf+meta:vp+{}+title{${2:New document}}+{}+style)+body>(h1>{${3: New Document}})+{
{ "!": "{}+html[lang=${1}${lang}]>(head>meta:utf+meta:vp+{}+title{${2:New document}}+{}+style)+body>(h1>{${3: New Document}})+{${0}}" }
}" }
Breakdown
A string with the doctype:
{}
The
element with a
lang
attribute. The value of the
lang
attribute is a variable you can change in the VS code settings (Code → Preferences → Settings).
html[lang=${lang}]
You can change the default natural language of the page by searching for “emmet variables” in VS Code settings and changing the
lang
variable. You can add your custom variables here, too.

The
includes the
charset
meta tag,
viewport
meta tag,
, and
tag.
{}
creates a new line.
(head>meta:utf+meta:vp+{}+title{${2:New document}}+{}+style)
Let’s have a first quick look at what this gives us.
New document
Looks okay, but the
meta:utf
abbreviation creates the old way in HTML to define the
charset
and
meta:vp
creates two tab stops I don’t need because I never use a different setting for the
viewport
.
Let’s overwrite these snippets before we move on.
{ "meta:vp": "meta[name=viewport content='width=device-width, initial-scale=1']", "meta:utf": "meta[charset=${charset}]" }
Last but not least, the
element, an
with default text, followed by the final tab stop.
body>(h1>{${3: New Document}})+{
body>(h1>{${3: New Document}})+{${0}}
}
The final boilerplate:
New document
New Document
For me, that’s the perfect minimal debugging setup.
Boilerplate Medium
While I use the first boilerplate only for quick demos, the second boilerplate can be used for complex pages. The snippet creates the following:
- Basic site structure,
-
viewport
meta tag, - Page title,
-
.no-js
/.js
classes, - External screen and print stylesheets,
-
description
andtheme-color
meta tag, - Page structure.
{ "!!": "{}+html[lang=${lang}].no-js>{ }+(head>meta:utf+meta:vp+{}+title{${1:🛑 Change me}}+{}+(script[type="module"]>{document.documentElement.classList.replace('no-js', 'js');})+{}+link:css+link:print+{}+meta[name="description"][content="${2:🛑 Change me (up to ~155 characters)}"]+{ }+meta[name="theme-color"][content="${2:#FF00FF}"])+body>page" }
Yeaaah, I know, that looks like gibberish. Let’s dissect it.
Breakdown
The
doctype
and the root element are like in the first example, but with an additional
no-js
class and a comment that reminds me to change the
lang
attribute, if necessary.
{}+html[lang=${lang}].no-js>{ }
The TODO Highlight [15] extension makes the comment really pop.

The
includes the
charset
meta tag,
viewport
meta tag,
.
{}
creates a new line.
(head>meta:utf+meta:vp+{}+title{${1:🛑 Change me}}+{}
A script with a line of JavaScript. I’m
cutting the mustard
[16]
at the JS module support. If a browser supports JavaScript modules, it means that it’s a browser that supports modern JavaScript (e.g. modules, ES 6 syntax, fetch, and so on). I ship most JS only to these browsers, and I use the
js
class in CSS, if the styling of a component is different, when JavaScript is active.
(script[type="module"]>{document.documentElement.classList.replace('no-js', 'js');})+{}
Two
elements; the first links to the main stylesheet and the second to a print stylesheet.
link:css+link:print+{}
The page description:
meta[name="description"][content="${2:🛑 Change me (up to ~155 characters)}"]+{ }
The
theme-color
meta tag:
meta[name="theme-color"][content="${2:#FF00FF}"])
The body element and the basic page structure:
body>page
The final boilerplate looks like this:
Full Boilerplate
The full boilerplate is similar to the second boilerplate; the differences are additional
meta
tags and a
script
tag.
The snippet creates the following:
- Basic site structure,
-
viewport
meta tag, - Page title,
-
js
/no-js
classes, - External screen and print stylesheets,
-
description
and open graph meta tags, -
theme-color
meta tag, -
canonical
- Favicon tags,
- Page structure,
-
<
script>
tag.
{ "!!!": "{}+html[lang=${lang}].no-js>{ }+(head>meta:utf+meta:vp+{}+title{${1:🛑 Change me}}+{}+(script[type="module"]>{document.documentElement.classList.replace('no-js', 'js');})+{}+link:css+link:print+{}+meta[property="og:title"][content="${1:🛑 Change me}"]+meta[name="description"][content="${2:🛑 Change me (up to ~155 characters)}"]+meta[property="og:description"][content="${2:🛑 Change me (up to ~155 characters)}"]+meta[property="og:image"][content="${1:https://}"]+meta[property="og:locale"][content="${1:en_GB}"]+meta[property="og:type"][content="${1:website}"]+meta[name="twitter:card"][content="${1:summary_large_image}"]+meta[property="og:url"][content="${1:https://}"]+{ }+{}+link[rel="canonical"][href="${1:https://}"]+{ }+{}+link[rel="icon"][href="${1:/favicon.ico}"]+link[rel="icon"][href="${1:/favicon.svg}"][type="image/svg+xml"]+link[rel="apple-touch-icon"][href="${1:/apple-touch-icon.png}"]+link[rel="manifest"][href="${1:/my.webmanifest}"]+{}+meta[name="theme-color"][content="${2:#FF00FF}"])+body>page+{}+script:src[type="module"]" }
This incredibly long snippet creates this:
Custom CSS Snippets
For the sake of completeness, here are some of the CSS snippets I’m using.
Debugging
This snippet creates a 5px red outline with a custom offset.
"debug": "outline: 5px solid red;noutline-offset: -5px;"
Centering
A snippet that sets
display
to flex, and centers its child items.
"center": "display: flex;njustify-content: center;nalign-items: center;"
Sticky
Sets the
position
property to
sticky
, with two tab stops at the
top
and
left
property.
"sticky": "position: sticky;ntop: ${1:0};nleft: ${2:0};"
div
element.
User Snippets
At the beginning of this article, I mentioned that VS Code also provides custom snippets. The difference to Emmet snippets is that you can’t use abbreviations, but you can also define tab stops and make use of internal variables.
How to get the best out of user snippets could be a topic for another article, but here’s an example of a custom CSS snippet I’ve defined:
"Visually hidden": { "prefix": "vh", "body": [ ".u-vh {", " position: absolute;n white-space: nowrap;n width: 1px;n height: 1px;n overflow: hidden;n border: 0;n padding: 0;n clip: rect(0 0 0 0);n clip-path: inset(50%);n margin: -1px;", "}" ], "description": "A utility class for screen reader accessible hiding." }
This snippet doesn’t just create CSS rules, but a whole declaration block when we type
vh
and press
Enter
or
Tab
.
.u-vh { position: absolute; white-space: nowrap; width: 1px; height: 1px; overflow: hidden; border: 0; padding: 0; clip: rect(0 0 0 0); clip-path: inset(50%); margin: -1px; }
Final Words
It takes some time to create these snippets, but it’s worth the effort because you can customize Emmet to your personal preferences, automate repetitive tasks and save time in the long run.
I’d love to see which snippets you use, so please share them with us in the comments. If you want to use my settings, you can find my final snippets.json [17] on GitHub.
Resources

References
- ^ More about Manuel ↬ (www.smashingmagazine.com)
- ^ HTML boilerplate (www.matuzo.at)
- ^ VS Code (code.visualstudio.com)
- ^ user snippets (code.visualstudio.com)
- ^ HTML and CSS snippets and abbreviations (docs.emmet.io)
- ^ Emmet (emmet.io)
- ^ Emmet docs (docs.emmet.io)
- ^ abbreviation syntax (docs.emmet.io)
- ^ next section (www.smashingmagazine.com)
- ^ a bunch of HTML snippets (github.com)
- ^ Smashing Email Newsletter (www.smashingmagazine.com)
- ^ Small (www.smashingmagazine.com)
- ^ Medium (www.smashingmagazine.com)
- ^ Full (www.smashingmagazine.com)
- ^ TODO Highlight (marketplace.visualstudio.com)
- ^ cutting the mustard (fettblog.eu)
- ^ final snippets.json (gist.github.com)
Powered by WPeMatico