第一次接触Emmet是在2015年,当时我正在赶一个电商网站的前端页面。面对几十个重复的列表项和嵌套div,手指已经机械性地敲击着相同的标签结构。直到同事扔给我一行神奇的缩写:"ul>li.item$*5>a",瞬间生成完整HTML结构的那一刻,我才意识到自己浪费了多少生命在重复劳动上。
Emmet(前身为Zen Coding)本质上是一种"编写即生成"的标记语言速写工具。它通过类似CSS选择器的语法,让开发者能用极简的缩写表达复杂的HTML/CSS结构。目前所有主流编辑器(VS Code、Sublime、WebStorm等)都内置或通过插件支持Emmet,成为现代前端工作流的标准配置。
最基础的用法是输入元素名加叹号:
html复制div!
按Tab键后立即展开为:
html复制<div></div>
这看起来简单,但当配合编辑器多光标功能批量生成多个元素时,效率提升立竿见影。
用>表示父子关系,+表示兄弟关系:
html复制div>ul>li
展开为:
html复制<div>
<ul>
<li></li>
</ul>
</div>
而:
html复制header+main+footer
生成并列结构:
html复制<header></header>
<main></main>
<footer></footer>
最强大的特性之一是*乘法和$编号:
html复制ul>li.item$*5
生成带有序号的5个列表项:
html复制<ul>
<li class="item1"></li>
<li class="item2"></li>
<li class="item3"></li>
<li class="item4"></li>
<li class="item5"></li>
</ul>
在制作导航菜单或商品列表时,这个功能可以节省90%的编码时间。
方括号添加属性,花括号添加文本内容:
html复制a[href=# target=_blank]{点击这里}
展开为:
html复制<a href="#" target="_blank">点击这里</a>
Emmet对CSS属性也有系统的缩写规则:
m10 → margin: 10px;p20-30 → padding: 20px 30px;w100p → width: 100%;bg#f00 → background: #ff0000;用+连接多个属性:
css复制m10+p20-30+bg#f00
展开为:
css复制margin: 10px;
padding: 20px 30px;
background: #ff0000;
添加-自动生成带前缀的属性:
css复制-trfs
展开为:
css复制-webkit-transform: ;
-moz-transform: ;
-ms-transform: ;
-o-transform: ;
transform: ;
在VS Code中建议设置:
json复制"emmet.triggerExpansionOnTab": true,
"emmet.includeLanguages": {
"javascript": "javascriptreact",
"vue-html": "html"
}
这样不仅在.html文件中,在Vue单文件组件和JSX里也能使用Emmet。
在设置中追加自定义缩写:
json复制"emmet.extensionsPath": "~/emmet"
然后创建自定义snippets.json:
json复制{
"html": {
"snippets": {
"bootstrap5:cdn": "<link href='https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css' rel='stylesheet'>"
}
}
}
缩写不生效:
生成结构不符合预期:
>和+的优先级差异(header>h1)+(main>section)特殊字符冲突:
class需写为className$符号冲突时可改用\转义以创建一个Bootstrap风格的卡片组件为例:
传统写法:
html复制<div class="card" style="width: 18rem;">
<img src="..." class="card-img-top" alt="...">
<div class="card-body">
<h5 class="card-title">Card title</h5>
<p class="card-text">Some quick example text.</p>
<a href="#" class="btn btn-primary">Go somewhere</a>
</div>
</div>
手动输入约需90秒,且容易漏写闭合标签。
Emmet写法:
html复制.card[style="width: 18rem;"]>img.card-img-top[src=... alt=...]+.card-body>h5.card-title{Card title}+p.card-text{Some quick example text.}+a.btn.btn-primary{href=#}{Go somewhere}
仅需15秒,结构绝对正确,且修改样式时只需调整一处。
配合编辑器命令,可将Emmet与文件模板结合。例如在VS Code中创建new-component.html:
html复制<!DOCTYPE html>
<html lang="en">
<head>
${1|meta,title,link|}
</head>
<body>
${2:<!-- Content -->}
</body>
</html>
使用时通过!快速填充基础结构。
利用乘法运算符快速创建栅格系统:
html复制.container>.row>.col-sm-6*2
生成:
html复制<div class="container">
<div class="row">
<div class="col-sm-6"></div>
<div class="col-sm-6"></div>
</div>
</div>
在CSS预处理器中同样有效:
scss复制@mixin card {
.card {
w300+h200+bdrs10
&-header { p15+bg#f8f9fa }
}
}
展开后:
scss复制@mixin card {
.card {
width: 300px;
height: 200px;
border-radius: 10px;
&-header {
padding: 15px;
background: #f8f9fa;
}
}
}
掌握Emmet后,我的前端开发效率提升了至少3倍。特别是在迭代修改阶段,不需要再费力调整嵌套结构,只需修改缩写表达式即可同步更新所有相关标签。对于长期维护的项目,这种编码方式也能显著降低人为错误率。