答案是:检查文件后缀是否为.html/.htm、右下角语言模式是否为html、光标是否在空行或行首;三者缺一不可,否则!或html:5按tab无反应。

! 或 html:5 按 Tab 没反应?检查这三件事
VS Code 默认支持 Emmet,根本不需要装插件来生成 HTML 骨架——但很多人卡在这一步,以为功能坏了。
常见现象是敲 ! 后按 Tab 什么都没出来,或者只补全了局部标签(比如只生成 不带 )。
- 文件后缀必须是
.html 或 .htm;如果是 .txt 或未保存的空白文件,Emmet 完全不触发
- 右下角语言模式必须显示为
HTML,不是 Plain Text —— 点击那里手动选一次就能切过去
- 光标必须在空行或行首;如果前面有空格、制表符,甚至中文标点,Emmet 就会失效
顺带一提:html:5 和 ! 效果完全一样,后者更短,但两者都依赖同一套机制,别试 html:4 或 html:basic,这些缩写在当前 VS Code 版本(截至 2026 年)已弃用。
ul>li*5 这类嵌套结构总缺闭合标签?关掉 Auto Close Tag 插件
看起来是“自动补全”没起作用,其实是两个插件在打架:VS Code 自带的 Emmet 展开和第三方插件 Auto Close Tag 对标签生命周期的理解不同。
Emmet 展开时生成的是完整结构(含开始+结束标签),而 Auto Close Tag 会在你输入 <div> 时再额外插入 <code>
,结果就是
<div></div> 这种重复闭合。
- 遇到嵌套展开后多出闭合标签,先禁用
Auto Close Tag,只靠 Emmet 原生能力就够用
- 如果确实需要实时补全单个标签(比如边写边补
<p></p>),可以保留它,但务必在设置里关掉 autoCloseTag.enableAutoCloseTag 的全局开关,只对特定语言启用
-
Auto Rename Tag 可以留着,它只响应你手动修改标签名的动作,不影响 Emmet 展开
想改默认骨架里的 lang="en" 或加 meta description?别动源码,用用户代码片段
VS Code 的 ! 展开内容是硬编码的,没法通过设置直接改。有人试图去改安装目录里的内置模板,结果升级后被覆盖,白忙一场。
正确做法是用 VS Code 自带的用户代码片段(User Snippets)覆盖它:
- 打开命令面板(
Ctrl+Shift+P),搜 Preferences: Configure User Snippets
- 选
html.json(如果没有就新建)
- 填入这段配置:
{
"html5": {
"prefix": "!",
"body": [
"",
"",
"",
" <meta charset='\"UTF-8\"'>",
" <meta name='\"viewport\"' content='\"width=device-width,' initial-scale='1.0\"'>",
" <meta name='\"description\"' content='\"${1:页面描述}\"'>",
" <title>${2:页面标题}</title>",
"",
"",
" ${0}",
"",
""
],
"description": "自定义 HTML5 骨架"
}
}
注意:prefix 设为 ! 才能覆盖默认行为;${1:xxx} 是可跳转占位符,Tab 键可依次编辑;${0} 是最终光标落点位置。
复杂结构手写太慢?用 Emmet 组合语法一次性搞定
别一行行敲 <section><article><header><h1></h1></header></article></section>……Emmet 的组合规则比想象中灵活得多,关键是理解符号优先级。
例如要生成一个带 ID、类、属性和文本的导航菜单,直接输:nav#main-nav.navbar>ul>li*3>a[href="#${$}"]{菜单项 $},再按 Tab:
<nav id="main-nav" class="navbar"><ul>
<li><a href="#1">菜单项 1</a></li>
<li><a href="#2">菜单项 2</a></li>
<li><a href="#3">菜单项 3</a></li>
</ul></nav>
-
# 和 . 必须紧跟标签名,中间不能有空格;[href="#"] 要用方括号,不能写成 href="#"
-
$ 在 *n 后自动递增,但只对紧邻它的部分生效;{菜单项 $} 中的 $ 和前面的 *3 是绑定的
- 括号
() 用来分组,比如 (div>p)*2 会生成两组 <div><p></p></div>,而不是 <div>
<p></p>
<p></p>
</div>
真正容易被忽略的,是 Emmet 对空格极其敏感——div .cls(中间有空格)会被当成两个独立标签,而 div.cls(无空格)才是带 class 的 div。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!