HTML 编码规约
1 文档结构
1.1 文件样板
<!doctype html>
<html lang="en-US">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1" />
<title>My Site - There are a lot of fun!</title>
<meta name="description" content="web front-end coding and engineering specification" />
<meta name="keyword" content="code,html,css,javascript,typescript,react,node" />
<link rel="stylesheet" href="index.css" />
</head>
<body>
<div id="root"></div>
<script src="./index.js"></script>
</body>
</html>
1.2 DOCTYPE
文档开头必须有 doctype
强制
<!-- ❌ 缺少 doctype -->
<html lang="zh-CN"></html>
<!-- ❌ doctype 位置错误 -->
<html lang="zh-CN">
<!doctype html>
</html>
<!-- ✅ 正确 -->
<!doctype html>
<html lang="zh-CN"></html>
必须使用 HTML5 小写 doctype
强制
<!-- ❌ xhtml doctype -->
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html lang="zh-CN"></html>
<!-- ❌ html4 doctype -->
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html lang="zh-CN"></html>
<!-- ❌ html5 大写 (旧) -->
<!-- prettier-ignore -->
<!DOCTYPE html>
<html lang="zh-CN"></html>
<!-- ✅ html5 小写 (新) -->
<!doctype html>
<html lang="zh-CN"></html>
1.3 <html> 元素
必须有且仅有一个位于顶层的 <html> 元素
强制
<!-- ❌ 缺少 <html> -->
<script></script>
<div>...</div>
<!-- ❌ 多个 <html> -->
<html lang="zh-CN"></html>
<html lang="zh-CN"></html>
<!-- ❌ <html> 嵌入了其他元素中 -->
<div>
<html lang="zh-CN"></html>
</div>
<!-- ❌ 其他元素插入到了 <html> 之外 -->
<html lang="zh-CN"></html>
<script></script>
<div>...</div>
<!-- ✅ 正确 -->
<!doctype html>
<html lang="zh-CN">
<head>
...
</head>
<body>
...
</body>
</html>
必须有 lang 属性
强制
lang 属性有助于搜索引擎、屏幕阅读器、翻译工具的正常工作。属性的值通常是 语言-地区 格式,如 en-US, zh-CN。
<!-- ❌ 缺少 lang -->
<html></html>
<!-- ❌ 大小写错误 -->
<html lang="zh-cn"></html>
<!-- ❌ 不要使用下划线 -->
<html lang="zh_CN"></html>
<!-- ✅ 正确 -->
<html lang="zh-CN"></html>
如果文档中的部分内容是其他语言,则应该在其根元素上添加对应的 lang 属性。
<!doctype html>
<html lang="zh-CN">
<head>
...
</head>
<body>
<header>...</header>
<main>...</main>
<footer lang="en-US">...</footer>
</body>
</html>
有且仅有一个 <head> 和一个 <body>
强制
<!-- ❌ 缺少 <head> -->
<!doctype html>
<html lang="zh-CN">
<body>
...
</body>
</html>
<!-- ❌ 其他元素作为内容 -->
<!doctype html>
<html lang="zh-CN">
<head>
...
</head>
<body>
...
</body>
<!-- script 只能放在 <head> 或 <body> 中 -->
<script></script>
</html>
<!-- ✅ 正确 -->
<!doctype html>
<html lang="zh-CN">
<head>
...
</head>
<body>
...
</body>
</html>
1.4 <meta> 元素
<meta> 元素必须包含在 <head> 元素内
强制
<!-- ❌ <meta> 在 <body> 里 -->
<!doctype html>
<html lang="zh-CN">
<head>
...
</head>
<body>
<meta charset="utf-8" />
</body>
</html>
<!-- ✅ 正确 -->
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="utf-8" />
</head>
<body>
...
</body>
</html>
必须使用 UTF-8 字符编码
强制
<head>
<meta charset="utf-8" />
</head>
响应式页面应当设置 viewport
推荐
让页面大小适配设备实际尺寸,用户可以用手势缩放页面内容。
<head>
<meta name="viewport" content="width=device-width, initial-scale=1" />
</head>
以下设置禁用了缩小,因为缩小通常用处不大,且容易带来问题。
<head>
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1" />
</head>
如果网页内 UI 支持缩放手势,则你需要完全禁用浏览器的缩放手势支持。
<head>
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no" />
</head>
要适配 iPhone 的刘海屏,可能需要额外的配置。了解更多 .
1.5 资源加载
-
1.5.1
推荐引入 CSS 和 JavaScript 时无需指定 type。 根据 HTML5 规范,引入 CSS 和 JavaScript 时通常不需要指明 type,因为 text/css 和 text/javascript 分别是他们的默认值。<!-- bad --><link type="text/css" rel="stylesheet" href="example.css" /><style type="text/css">/* ... */</style><script type="text/javascript" src="example.js"></script><!-- good --><link rel="stylesheet" href="example.css" /><style>/* ... */</style><script src="example.js"></script> -
1.5.2
推荐在 head 标签内引入 CSS,在 body 结束标签前引入 JS。在
<body></body>中指定外部样式表和嵌入式样式块可能会导致页面的重排和重绘,对页面的渲染造成影响。因此,一般情况下,CSS 应在<head></head>标签里引入,了解更多。在 HTTP2(Chrome 浏览器 69 版本之后,Firefox 和 Edge)中可以在 body 中使用 link 标签引入样式文件,但不推荐在 body 中使用
<style>标签的内联样式。<link rel="stylesheet">将会阻止后续内容的渲染,而不是整个页面。除了基础库等必须要在 DOM 加载之前运行的 JavaScript 脚本,其他都在靠近
body结束标签前引入,以防止出现页面渲染的阻塞,了解更多。<!-- bad --><!doctype html><html><head><script src="mod-a.js"></script><script src="jquery.js"></script></head><body><style>.mod-example {padding-left: 15px;}</style></body></html><!-- good --><!doctype html><html><head><style>.mod-example {padding-left: 15px;}</style></head><body>...<script src="path/to/my/script.js"></script></body></html> -
1.5.3
推荐外部资源的引用地址跟随页面协议,省略协议部分。<link rel="stylesheet" href="//g.alicdn.com/lib/style/index-min.css" /> -
1.5.4
推荐使用 preload 预加载关键资源,了解更多。<link rel="preload" href="style.css" as="style" /><link rel="preload" href="main.js" as="script" /> -
1.5.5
推荐使用 dns-prefetch 和 preconnect 处理 DNS 解析延迟问题,提高网页加载性能,了解更多。<link rel="preconnect" href="https://fonts.googleapis.com/" crossorigin /><link rel="dns-prefetch" href="https://fonts.googleapis.com/" />
1.6 页面标题
- 1.6.1 页面需要指定 title 标签,有且仅有 1 个。
强制<head><meta charset="utf-8" /><title>淘宝网 - 淘!我喜欢</title></head>
2 编码风格
2.1 缩进
-
2.1.1
推荐统一使用 2 个空格缩进,不要使用 4 个空格或 tab 缩进。<!doctype html><html><head><title>Page title</title></head><body><img src="images/company-logo.png" alt="Company" /><h1 class="hello-world">Hello, world!</h1></body></html>
2.2 注释
-
2.2.1 在 HTML 注释代码中,不允许出现任何敏感信息。
强制常见的敏感信息包括:- 业务相关敏感信息,例如业务规则
- 员工个人隐私信息,例如邮箱、手机、身份证号码
- AK(accessKey id, accesskey secret)
- 证书、密码
- 内网 IP、URL
- 其他公司、员工相关的内部信息、敏感信息
-
2.2.2
推荐单行注释,需在注释内容和注释符之间需留有一个空格,以增强可读性。<!-- 单行注释 --> -
2.2.3
推荐多行注释,注释符单独占一行,注释内容 2 个空格缩进。<!--多行注释多行注释-->
2.3 标签
-
2.3.1 标签名统一使用小写。
强制<!-- bad --><H1>Hello, world!</H1><!-- good --><h1>Hello, world!</h1> -
2.3.2
推荐不要省略自闭合标签结尾处的斜线,且斜线前需留有一个空格。虽然 HTML5 规范 中指出结尾的斜线是可选的,但保留它们可以明确表达该标签已闭合的语义,更易于维护和理解。
同时,在 React 被广泛使用的今天,这与 JSX 的规范 相一致,JSX 中自闭合标签必须保留结尾的斜线。
<!-- bad --><meta name="viewport" content="width=device-width, initial-scale=1.0"><img src="images/foo.png" alt="foo"><!-- good --><meta name="viewport" content="width=device-width, initial-scale=1.0" /><img src="images/foo.png" alt="foo" />
2.4 属性
-
2.4.1 属性值使用双引号,不要使用单引号。
强制<!-- bad --><link rel='stylesheet' href='example.css' /><!-- good --><link rel="stylesheet" href="example.css" /> -
2.4.2
推荐不要为 Boolean 属性添加取值。XHTML 需要每个属性声明取值,但是 HTML5 并不需要。一个元素中 Boolean 属性存在即表示取值
true,不存在则表示取值false,了解更多。<!-- bad --><input type="text" disabled="disabled" /><input type="checkbox" value="1" checked="checked" /><select><option value="1" selected="selected">1</option></select><!-- good --><input type="text" disabled /><input type="checkbox" value="1" checked /><select><option value="1" selected>1</option></select> -
2.4.3
推荐自定义属性的命名:以 data- 为前缀。建议自定义属性的命名都以
data-为前缀,以便区分。<!-- bad --><a modal="toggle" href="#"> Example link </a><!-- good --><a data-modal="toggle" href="#"> Example link </a>
2.5 语义化
-
2.5.1
参考尽量根据语义使用 HTML 标签。HTML 标签(更严谨的叫法是 HTML 元素)都有其语义,例如
p标签即"paragraphs"用于章节,a标签即"anchors"用于锚点链接,了解更多。我们应优先选取符合当下所需语义的标签,这既有助于可访问性(Accessibility),也可以在 CSS 加载失败时获得较好的展示效果。
<!-- bad --><div class="list"><div class="list-item">1</div><div class="list-item">2</div><div class="list-item">3</div></div><!-- good --><ul class="list"><li class="list-item">1</li><li class="list-item">2</li><li class="list-item">3</li></ul>
2.6 可访问性
-
2.6.1
参考注意 HTML 的可访问性(Accessibility)。网页可访问性使网页内容落实"无障碍",让不同程度或需求的用户可以顺畅的获取网站上的信息。传统上我们认为这只与残疾人士有关,但提升网站的可访问性也可以让其他用户群体受益,比如使用移动设备的人群或低速网络的人群。
例如,为 img 标签设置 alt 属性:
<!-- bad - 缺少 alt 属性,无法被无障碍阅读器识别 --><img src="hello.jpg" /><!-- good --><img src="hello.jpg" alt="Welcome to visit!" /><!-- good - 图片无需被无障碍阅读器识别时 --><img src="logo.jpg" alt="" /><!-- good - 图片无需被无障碍阅读器识别时 --><img src="logo.jpg" role="presentation" />了解更多 HTML 可访问性的知识,可以阅读这篇 MDN 的文章。
3 模板语言
有非常多不同的模板语言被用来动态生成 HTML 文件,例如 [Nunjucks], [EJS]。编写模板语言代码时,也应该遵循一些常见规约。
此部分以 [Nunjucks] 作为示例,但是同样也适用于其他模板语言。
变量,过滤器和关键字必须有前后空格
强制
{# ❌ 错误,没有空格 #}
{{username}} {{tags|join(',')}}
{# ✅ 正确 #}
{{ username }} {{ tags | join(',') }}
未过滤的用户输入必须 HTML 转义
强制
{# ❌ 错误 #}
<p>{{ description }}</p>
<script>
window.user = {{ user | dump }}
</script>
{# ✅ 正确 #}
{{ description | escaped }}
<script>
window.user = {{ user | dump | escaped }}
</script>
作者署名
如果您为本文档编写做出过贡献,但您的名字却没有列出,请创建 Issue 告诉我们!
- TODO