为 HTML 加上 lang 属性
如:
<html lang="zh-CN">
<p lang="zh">
可以看到,由于 lang
是全局属性,因此可以指定在任意元素上。
此外,如果一个元素上指定了 lang
,那么该元素的子元素的语言也会被认为是 lang
,即 lang
属性会被继承。
所以,如果我们在 <html>
元素上写明了 lang
,那么我们也就为整个页面指定了 lang
。
要想为整个页面指定语言,我们还可以使用 meta 标签,如:
<meta http-equiv="content-language" content="zh-CN">
lang
属性中的语言标签的格式规范由 BCP47 定义,其形式如 ll
, ll-CC
, ll-Script-CC
。具体如 zh
, zh-CN
, zh-Hant-TW
。示例中所用的大小写为推荐写法,不过语言标签本身是大小写无关的。
为什么要为页面指明 lang
那么我们为什么要为页面指明 lang 属性呢?
这里至少有两方面的考虑,其一在于样式,其二则在于搜索引擎优化。
样式
当我们没有为 html 或其他元素指明所要用的字体(font-family
)时,浏览器就会使用一套默认的字体,而其所选用的字体是语言相关的。因此,为页面指明语言,可以帮助浏览器更好地选择默认字体。
SEO(搜索引擎优化)
搜索引擎索引网站内容时也需要知道网站适用的语言和国家/地区,从而能够更好地为用户返回搜索结果。
如页面上缺失相关语言信息,搜索引擎往往也会给出警告。
如 Bing 就会报告页面缺失 meta language 信息:
注意:Bing 的建议操作中提到也可以在 <title>
标签上使用 lang
属性,但我并不推荐这么做,因为在 <title>
上写明的 lang
属性只对 <title>
元素生效,而不能代表页面上其他元素的语言。
通过 JS, CSS 访问 lang 属性
我们已经知道了如何在 HTML 中为一个元素指定 lang
属性,同样的,我们也可以在 JS 中访问指定元素的 lang
,或为其设定一个新的 lang
。
var el = document.querySelector('html');
// 获取元素的 lang
var lang = el.lang;
// 为元素设定新的 lang
el.lang = 'en';
如果需要在 CSS 中根据元素的 lang
来设定相应的样式,我们也有多种写法:
/* 写法一: 仅匹配指明了 lang 属性的元素 */
/* 使用这种写法我们可以写一些会被继承的 CSS 规则,
或只适用于有 lang 属性的规则。 */
[lang="zh-CN"] {
/* CSS 规则 */
}
/* 写法二: 匹配所有指明了语言的元素 */
/* 该写法与写法一所不同的是,不仅会匹配指明了 lang 属性的元素,
也会匹配其子元素,因为 lang 属性是会被继承的。 */
/* 注意: IE < 8 不支持 :lang */
:lang(zh-CN) {
/* CSS 规则 */
}
/* 写法三: 混合写法一和写法二 */
[lang]:lang(zh-CN) {
/* CSS 规则 */
}
有了以上几种写法后,我们举例来说这些写法到底能匹配到什么元素,比如有如下页面:
<html lang="zh">
<head></head>
<body>
<div id="div1" lang="zh-CN">
<p id="p1"></p>
</div>
<div id="div2" lang="zh-TW">
<p id="p2"></p>
</div>
<div id="div3" lang="zh-cn">
<p id="p3"></p>
</div>
<div id="div4" lang="zh-tw">
<p id="p4"></p>
</div>
<div id="div5" lang="en">
<p id="p5"></p>
</div>
</body>
</html>
-
[lang="zh-cn"]
会匹配到#div1
和#div3
; -
[lang="zh"]
只会匹配到html
; -
:lang(zh-CN)
会匹配到#div1
,#p1
,#div3
和#p3
; -
:lang(zh)
会匹配到html
,head
,body
,#div1
,#p1
,#div2
,#p2
,#div3
,#p3
,#div4
和#p4
。 即除#div5
和#p5
的所有元素; -
:lang(en)
会匹配到#div5
和#p5
; -
[lang]:lang(zh)
会匹配到html
,#div1
和#div3
。
以上示例中,我们也可以看到无论是 CSS 选择器中的语言标签还是 lang
属性中的语言标签都是大小写不敏感的。
实例
实际使用中,比较常见的用法就是根据语言的不同,选用不同的字体,如 Zzz.buzz 的样式中有如下代码:
body {
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
}
[lang]:lang(en),
:lang(en) body {
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
}
[lang]:lang(zh),
:lang(zh) body {
font-family: "Microsoft YaHei", sans-serif;
}
pre, code {
font-family: Consolas, Menlo, Monaco, "Lucida Console", "Liberation Mono", "DejaVu Sans Mono", "Bitstream Vera Sans Mono", "Courier New", monospace;
}
:lang(zh) pre, :lang(zh) code {
font-family: Consolas, Menlo, Monaco, "Lucida Console", "Liberation Mono", "DejaVu Sans Mono", "Bitstream Vera Sans Mono", "Courier New", "Microsoft Yahei", monospace;
}
上述代码中之所以要在 body
选择器上直接指明字体,一是为了为 en
和 zh
之外的语言设置默认字体,二是为了兼容 IE 6, 7,因为 IE 6, 7 不支持 :lang
选择器。
另外,之所以写成 [lang]:lang(zh), :lang(zh) body
的形式, 而不简写为 :lang(zh)
是为了避免覆盖 pre, code, tt, kbd
等元素的默认样式。
上述 pre, code
中的字体列表取自 StackOverflow 的样式。