大多数前端工程师了解但并不擅长的HTML语义化

下面两段代码从HTML语义化的角度来看有什么问题?

1
2
3
4
5
6
7
<!-- 示例1 -->
<label>作者: <input type="author" texture="deep pile"></label>
<!-- 示例2 -->
<body>
<h1>【深度】扒开V8引擎的源码,我找到了你们想要的前端算法</h1>
<h2>下次面试官再问算法,用它怼回去!</h2>
...

读者可以先试试将上面例子中的代码进行语义化,再来看文末的答案。

HTML 语义化(按照 W3C 规范正确地使用标签元素和其属性,以下简称“语义化”,HTML 指 HTML5)被很多文章提到,但内容大多是先宣传语义化的必要性,然后劝说读者在开发中多使用语义化标签。

本文不宣传必要性, 也不卖力推荐大多数读者能写出语义化的代码,只对语义化的现状进行探究,并给出可行的语义化操作方式。

语义化的现状

我们以非语义化标签的滥用为例来看看目前网页的语义化程度。

非语义化的标签其实只有两个 div 和 span,本来这两个标签只是作为默认标签的补充,但现实是它们的使用频率却远超其它语义化标签。

下面是一段统计标签数量的 js 脚本,用它可以统计出网页上各个标签数量和占比。

打开浏览器控制台,执行下面的代码就可以得到结果。

1
2
3
4
5
6
7
8
9
10
11
12
var total = 0
var obj = Array.prototype.reduce.call(document.querySelectorAll('*'), (acc, cur) => {
let tag = cur.tagName.toLowerCase()
acc[tag]= acc[tag] || 0
acc[tag]++
total++
return acc
}, {})
var list = []
for(let k in obj) list.push({tag: k, times: obj[k], ratio: (obj[k] * 100 / total).toFixed(2) + '%'})
console.clear()
console.table(list.sort((a, b) => b.times - a.times))

先来看看我们使用最频繁的搜索引擎页面,语义化程度为67.5%

最好实现语义化的页面莫过于文章帖子类的页面,但是某博客网站页面语义化程度61.29%

再看看市值排行世界前列的某电商网站页面,语义化程度为43.19%

更多的统计数据就不贴出来了,总体情况是语义化程度很低。

为什么语义化如此不受待见?

语义化的阻碍

我们来看看现实开发场景中是如何一步一步地把工程师推向无语义化的道路上的。

语义化的成本

HTML定义了100多个标签,如果要把它们全部记住,确实有些难度。

即使分类记忆,也有十几类,如果再加上各个标签不同的属性,记忆量并不算小。

所以使用的时候可能还需要查文档。

就开发效率来说不如直接使用 div 和 span 来实现功能。

语义化的收益

使用一项技术,首先考虑其收益,或者说它能解决什么问题,那么语义化能带来什么呢?

  • 代码可读性提升。
  • 利于SEO。
  • 关爱视觉障碍用户。

说了这么多,其实归纳起来就一点:增强可识别性

识别性的重要性不言而喻,没有识别性就像电影《风语咒》中那个村里很多人都叫王富贵,喊一声王富贵一片人回头。

如此说来语义化势在必行?

非也~

HTML 语义化并不是实现可识别性的唯一手段,标签 id、属性、样式名都可以。

写个CSS样式类,顺便就把识别性的问题解决了(试想一下,如果不能自定样式,或者样式只能使用类选择器,谁还能不语义化?),样式类重复再通过属性或id来识别。

和前面这几种方式相比,语义化没有明显的使用收益。

非语义化的损失

从开发者的角度考虑,如果不使用语义化的标签会有什么坏处呢?

很遗憾,几乎没有~

  • 论代码的可读性,可不是HTML语义化就能解决的,况且id和css样式类几乎也能解决。
  • 论SEO,其它手段也有:写好 meta 标签,多用链接。当然花钱肯定是最直接见效的。
  • 至于考虑视觉障碍用户,这个需求的优先级就不用过多解释了,中小型公司压根都不会考虑。

既然底层开发者没有语义化的动力,那么管理者是否能通过规则来推动语义化呢?

我在《3种常见的代码规范类型》提到过,如果要让规则落地执行,光靠人的自律是很难实现的,靠人力来实现他律效率又太低,所以建立自动化的校验机制,将人力他律作为补充,才是高效的方案。

很多时候我们会用到代码检查工具比如 eslint、tslint ,HTML 的检查工具也有几个,不过这些检查工具只能做语法检查,无法进行语义检查。

举个例子,用驼峰命名规则可以检查出 parent_node 这种变量名称不符合规范,但对于一个变量是该叫a还是该叫user检查工具则无能为力了。

所以强制语义化这条路也走不通。

语义化真的只能放弃吗?

对于大多数工程师而言,恐怕是的。

编写语义化代码并不能直接带来开发效率提升,也不能凭此得到领导赏识而升职加薪……

但对于有技术追求的工程师而言,并不是!

他们知道做对的事比做容易的事更重要!

语义化之路

如果你已决定踏上语义化的道路,相信以下3个步骤可以帮助你。

1.正确标签使用属性

对于具有一定开发经验的工程师而言,非语义化的编程习惯是长久形成的,需要一口气全部改掉之前的编程习惯很难。

不建议一口气把所有标签全部记下来,然后把之前的页面推倒重写,全盘实现语义化。

比较耗时耗力,很容易生成挫败感而放弃。

所以推荐的方式是逐步实现语义化,从一个标签甚至一个属性开始。具体例子请看示例1

这一阶段重要的是养成语义化的习惯。

很多情况下能坚持下来形成习惯就已经成功一半了。

2.理解文档结构

养成习惯以后就可以从结构上考虑页面的语义化了。

非语义化最主要的问题就是 div 和 span 标签滥用。

完全不使用 div 和 span 并不现实,毕竟这两个标签被发明出来也是有使用价值的。

所以可以首先找出一些容易被滥用的区域,这样就能大大增加页面语义化的程度。

首先要考虑的就是减少不必要的 div 和 span 标签,然后才是考虑用合适的语义化标签来取代。

比如日常开发中和文本相关的内容比较多,那么考虑使用 h1~h6 , p , q , b … 这些标签来取代 div 和span。

即使是布局方面也可以使用一些结构性标签,如: main , section , footer , aside , header 来取代 div。具体例子请看示例2

3.分类记忆

如果要做到完全语义化,还可以利用工具。

下面是一张 html5 使用流程图,仅供参考。

W3C 也给出了一个分类方法,很形象,动画图如下:

具体效果可以查看这个网站

参考以上两张图,我整理了一个操作性更强的版本。

首先一些基础标签我们不需要考虑在内,尤其是在开发单页应用的时候,我们主要考虑开发组件时可能用到的标签。

!DOCTYPE,html,head,meta,base,link,style,body,script,noscript,<!-- -->

然后将剩下几十个标签进行分类,不一定完全贴切,但便于记忆和使用。

当然无论使用那种方式,前提还是记住这些标签的含义和属性。

这戏工具的作用只是在我们写页面的时候,帮我们快速准确地判断要使用哪个标签。

总结

语义化就像是前端成长道路上的一颗石子,失去每一颗石子似乎都不会造成影响,但只有聚集更多的石子才能铺成更长的路~

熟练编写语义化的页面并不能直接帮你成为高级前端工程师,但语义化却能体现前端工程师的工作习惯和技术素养。

1
2
3
4
5
6
7
8
9
10
11
12
13
<!-- 示例1语义化 -->
<!-- type值修改为浏览器可识别的值 -->
<!-- 自定义属性使用data前缀 -->
<label>作者: <input type="text" class="author" data-texture="deep pile"></label>

<!-- 示例2语义化 -->
<!-- 当出现主标题和子标题时,应使用hgroup标签作为父元素 -->
<body>
<hgroup>
<h1>【深度】扒开V8引擎的源码,我找到了你们想要的前端算法</h1>
<h2>下次面试官再问算法,用它怼回去!</h2>
</hgroup>
...

附上答案同时再给读者留一道思考题:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<!-- 可点击的图标 -->
<div class="lazy avatar avatar loaded immediate"></div>
<!-- 点击后弹出的菜单 -->
<ul class="nav-menu user-dropdown-list">
<div class="nav-menu-item-group">
<li class="nav-menu-item">
<a href="/user/592447fb44d904006ce996f8" class="link-icon">
<i class="fengwei fw-person"></i>
<span>我的主页</span>
</a>
</li>
<li class="nav-menu-item">
<a href="/user/592447fb44d904006ce996f8/likes">
<img src="https://b-gold-cdn.xitu.io/v3/static/img/zan.e9d7698.svg" class="zan">
<span>我赞过的</span>
</a>
</li>
<li class="nav-menu-item">
<a href="/user/592447fb44d904006ce996f8/collections">
<img src="https://b-gold-cdn.xitu.io/v3/static/img/collect.02e2979.svg" class="collect">
<span>我的收藏集</span>
</a>
</li>
</div>
<div class="nav-menu-item-group">
<li class="nav-menu-item">
<a>
<i class="fengwei fw-logout"></i>
<span>登出</span>
</a>
</li>
</div>
</ul>

参考:


原文链接:https://tech.gtxlab.com/html-tag.html

作者信息:朱德龙人和未来高级前端工程师。