Emmet: 第一个 Emmet 简写:基础标签与隐式标签名
学会
div、p、h1的简写只是第一步——Emmet 的"隐式标签名"才是真正让你提效的魔法:.box不写div也能展开。
1. 你将学到
- 基础标签的简写形式:
divph1spana等 - 隐式标签名(Implicit tag names)的核心规则
- HTML 与 CSS 上下文中省略行为的差异
- 类选择器
.class与 ID 选择器#id的简写 - 多 class 链
.btn.btn-primary的用法与综合实战
2. 一个前端开发者的真实故事
(1) 痛点:每个 div 都要手写,浪费时间
Alice 写了一个电商首页的卡片网格。她需要 3 张卡片,每张卡片里有图片、标题、描述、按钮。手动写的话,每张卡片是这样的结构:
<div class="card">
<img src="" alt="">
<h3 class="title"></h3>
<p class="desc"></p>
<button class="btn">购买</button>
</div>
一个 div 卡片 5 行,3 张卡片就是 15 行;如果要 6 张卡片就是 30 行。每个 div、每个 class、每个标签都要重复敲。Alice 算了一下时间:敲 30 行 HTML,她要花 6 分钟;而且每次手写都容易漏闭合标签或者写错引号。
(2) Emmet 简写的解法
Emmet 的解法是两点:第一,基础标签可以省略——在 HTML 上下文中,.box 等同于 div.box,省去 div 这个最常见的标签名;第二,重复结构用乘法 * 一行写完。Alice 用 Emmet 重写卡片网格:
.card*3>img+h3.title+p.desc+button.btn{购买}
一行简写,3 张卡片瞬间生成。card class 自动加到 div 上(因为省略了 div),按钮文字 {购买} 自动填入。30 行 HTML 变成 1 行简写,6 分钟的工作缩短到 5 秒。
(3) 收益
基础标签 + 隐式标签名是 Emmet 提效的第一级阶梯。掌握之后,Alice 写卡片网格从 6 分钟降到 5 秒,效率提升 70 倍。学完本课之后,你将能用一行 Emmet 简写完成 80% 的常见 HTML 结构搭建。
3. 基础标签简写
HTML 标签可以直接作为简写输入。常用基础标签的简写形式如下:
| 简写 | 展开结果 | 用途 |
|---|---|---|
div |
<div></div> |
最常用的容器 |
p |
<p></p> |
段落 |
h1 h2 h3 h4 h5 h6 |
<h1></h1> 等 |
标题(6 级) |
span |
<span></span> |
行内容器 |
a |
<a href=""></a> |
链接(自动带 href) |
ul ol |
<ul></ul> / <ol></ol> |
列表 |
li |
<li></li> |
列表项 |
table |
<table></table> |
表格 |
input |
<input type="text"> |
输入框(自动带 type) |
a 自动带 href="",input 自动带 type="text"),无需手动写。
4. 隐式标签名(Implicit Tag Names)
隐式标签名是 Emmet 提效的核心机制。当你写 .box 时,Emmet 会自动推断你想要的标签是 div,无需显式写 div.box。这个机制在 HTML 和 CSS 上下文中行为不同,需要分别理解。
| 上下文 | 简写 | 隐式推断为 | 展开结果 |
|---|---|---|---|
| HTML | .box |
div |
<div class="box"></div> |
| HTML | #main |
div |
<div id="main"></div> |
| HTML | ul>.item |
div(仅 .item 隐式) |
<ul><li class="item"></li></ul> |
| HTML | table>.row |
tr |
<table><tr class="row"></tr></table> |
| CSS | m10 |
(属性推导) | margin: 10px; |
| CSS | ! |
!important |
!important |
div,但在某些父元素内会自动切换(如 ul 内的 .item 变 li,table 内的 .row 变 tr,select 内的 .opt 变 option)。完整隐式规则见第 06 课。
5. 实战示例
下面 5 个示例覆盖了基础标签 + 隐式标签名的核心场景。学完这 5 个示例,你就能写 80% 的常见 HTML 结构。
▶ 示例:div 展开为 <div></div>(难度⭐)
最简单的 Emmet 简写:直接输入标签名。
缩写:
div
展开:
<div></div>
输出:
一行 div 容器,光标自动跳到标签内部,可以直接输入内容。`div` 是 HTML 中最常用的标签,Emmet 直接接受标签名作为简写。
▶ 示例:.container 隐式 div(难度⭐)
在 HTML 上下文中,省略标签名时默认推断为 div。
缩写:
.container
展开:
<div class="container"></div>
对比:显式写 div.container:
div.container
展开结果:
<div class="container"></div>
输出:
`.container` 和 `div.container` 完全等价。`div` 是 HTML 中最高频的标签,隐式机制可以省去 50% 的输入量。`#main` 同理:省略时默认推断为 `div`,展开为 `<div id="main"></div>`。
▶ 示例:#header.nav(难度⭐)
ID 选择器 # 和 class 选择器 . 可以混用在同一个标签上。
缩写:
#header.nav
展开:
<div id="header" class="nav"></div>
输出:
标签同时有 `id="header"` 和 `class="nav"` 两个属性。`#` 始终表示 ID,`.` 始终表示 class,顺序不影响展开结果。也可以加显式标签名 `header#top.nav` 展开为 `<header id="top" class="nav"></header>`。
▶ 示例:组合多个 class .btn.btn-primary(难度⭐⭐)
同一个标签可以有多个 class,用 . 链式连接。
缩写:
.btn.btn-primary.btn-lg
展开:
<div class="btn btn-primary btn-lg"></div>
进阶:配合标签名使用:
button.btn.btn-primary.btn-lg{加入购物车}
展开:
<button class="btn btn-primary btn-lg">加入购物车</button>
输出:
多个 class 之间用空格分隔。Emmet 不会限制 class 数量,常用于 Tailwind CSS、Bootstrap 等工具类框架(如 `class="btn btn-primary btn-lg text-center"`)。
▶ 示例:HTML 上下文 vs CSS 上下文(难度⭐⭐)
同一个简写在不同上下文中展开结果完全不同。这是 Emmet 最容易让初学者困惑的地方。
HTML 上下文(.html 文件):
.m10
展开:
<div class="m10"></div>
CSS 上下文(.css 文件):
.m10
展开:
margin: 10px;
输出:
在 HTML 文件中,`.m10` 被识别为"class 为 m10 的 div 标签";在 CSS 文件中,`.m10` 被识别为"margin 属性的简写"。Emmet 会根据当前文件类型自动切换模式。HTML 上下文遵循"省略标签名 → div"的隐式规则;CSS 上下文遵循"省略属性名 → 按首字母推导"的隐式规则(`m` 开头属性只有 `margin`,所以直接推导)。
6. 完整示例:综合三列卡片布局
把基础标签、隐式标签、* 乘法、> 嵌套组合起来,搭建一个电商首页常见的三列卡片网格。
▶ 示例:综合三列卡片布局(难度⭐⭐)
缩写:
.container>.row>.col*3>.card>img+h3.title+p.desc+button.btn{查看详情}
展开:
<div class="container">
<div class="row">
<div class="col">
<div class="card">
<img src="" alt="">
<h3 class="title"></h3>
<p class="desc"></p>
<button class="btn">查看详情</button>
</div>
</div>
<!-- 重复 2 次 (col + card 整体重复 3 次) -->
</div>
</div>
输出:
经典的电商三列卡片网格:1 个外层 container、1 个 row、3 个 col(每个 col 内包含完整 card)。`*3` 作用在 `.col` 上,因此 `.col` 重复 3 次;而 `>` 后面的 `.card>img+h3.title+p.desc+button.btn` 作为每个 col 的子元素,自动被复制 3 份。如果想让 `*3` 直接作用在 `card` 上(展开为 1 个 row + 3 张完整卡片),缩写应改为 `container>.row>.card*3>img+h3.title+p.desc+button.btn{查看详情}`。详细嵌套和乘法规则将在第 05 课展开。
❓ 常见问题
.box 和 div.box 完全等价吗?有没有例外?ul 内的 .item 会展开为 <li class="item">(不是 div),table 内的 .row 展开为 <tr>,select 内的 .opt 展开为 <option>,因为这些是"父元素语境下的合理子元素"。完整规则见第 06 课。a 简写展开后为什么自动带 href=""?a 自动带 href,input 自动带 type="text",img 自动带 src 和 alt,link 自动带 rel="stylesheet"。这是 Emmet 的"智能默认值",避免你手写这些必填属性。.m10 怎么报错?怎么禁用 CSS 简写?.m10 在 CSS 上下文是合法简写(展开为 margin: 10px;),不会报错。如果你的 CSS 文件中希望禁止 Emmet 简写,可以在 VSCode 设置中添加 "emmet.excludeLanguages": ["css"];但通常不建议禁用,因为 CSS 简写能让你少敲一半键盘。.btn.btn-primary 展开的 class 顺序重要吗?CSS 优先级会受影响吗?.btn.btn-primary 展开为 class="btn btn-primary")。CSS 优先级由样式表中规则顺序决定,与 class 字符串内的顺序无关,所以通常无影响。但如果你用 Tailwind 等工具类框架,建议按"布局 → 尺寸 → 颜色 → 状态"的顺序写,便于阅读。📖 小节
- 基础标签可直接作为简写:
divph1spana等 - HTML 上下文中省略标签名 → 默认推断为
div - 隐式标签在父元素语境内会切换:
ul内的.item→li,table内的.row→tr - ID 用
#,class 用.,可以混用:#header.nav展开为<div id="header" class="nav"></div> - 多 class 用
.链式连接:.btn.btn-primary.btn-lg - HTML 和 CSS 上下文中同一个简写展开结果完全不同,看文件扩展名决定模式
📝 作业
- 基础题(难度⭐):在 HTML 文件中分别输入
div、p、h1、span简写,按 Tab 后记录展开结果。然后试试.box和#main隐式 div 简写,对比 4 次展开的差异。 - 进阶题(难度⭐⭐):写一行 Emmet 简写,展开为包含 5 张卡片的网格(每张卡片有图片、标题、段落、按钮),并解释为什么
*5应该放在card上而不是其他位置。 - 挑战题(难度⭐⭐⭐):分别创建一个
.html文件和一个.css文件,在两个文件中输入.m10、.p20、#header三个简写,记录 6 次展开的结果,并写一份"HTML 与 CSS 上下文 Emmet 行为差异"对照表。