gitbook/重学前端/docs/78158.md
2022-09-03 22:05:03 +08:00

302 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# HTML语义div和span不是够用了吗
你好我是winter。
今天这篇是我们正式开篇的第一篇文章我想和你聊聊HTML。
我猜屏幕那一边的你估计会说“HTML我很熟悉了每天写这不是初级程序员才学的内容么这我还能不会吗
其实在我看来HTML并不简单它是典型的“入门容易精通困难”的一部分知识。深刻理解HTML是成为优秀的前端工程师重要的一步。
我们在上一篇文章中讲到了HTML的标签可以分为很多种比如head里面的元信息类标签又比如img、video、audio之类的替换型媒体标签。我今天要讲的标签是语义类标签。
## 语义类标签是什么,使用它有什么好处?
语义类标签也是大家工作中经常会用到的一类标签它们的特点是视觉表现上互相都差不多主要的区别在于它们表示了不同的语义比如大家会经常见到的section、nav、p这些都是语义类的标签。
语义是我们说话表达的意思,多数的语义实际上都是由文字来承载的。语义类标签则是纯文字的补充,比如标题、自然段、章节、列表,这些内容都是纯文字无法表达的,我们需要依靠语义标签代为表达。
在讲语义之前,我们来说说为什么要用语义。
现在我们很多的前端工程师写起代码来,多数都不用复杂的语义标签, 只靠div 和 span 就能走天下了。
这样做行不行呢?毫无疑问答案是行。那这样做好不好呢?按照正确的套路,我应该说不好,但是在很多情况下,答案其实是好。
这是因为在现代互联网产品里HTML用于描述“软件界面”多过于“富文本”而软件界面里的东西实际上几乎是没有语义的。比如说我们做了一个购物车功能我们一定要给每个购物车里的商品套上ul吗比如说加入购物车这个按钮我们一定要用Button吗
实际上我觉得没必要因为这个场景里面跟文本中的列表以及表单中的Button其实已经相差很远了所以我支持在任何“软件界面”的场景中直接使用div和span。
**不过,在很多工作场景里,语义类标签也有它们自己无可替代的优点。正确地使用语义标签可以带来很多好处。**
* 语义类标签对开发者更为友好使用语义类标签增强了可读性即便是在没有CSS的时候开发者也能够清晰地看出网页的结构也更为便于团队的开发和维护。
* 除了对人类友好之外语义类标签也十分适宜机器阅读。它的文字表现力丰富更适合搜索引擎检索SEO也可以让搜索引擎爬虫更好地获取到更多有效信息有效提升网页的搜索量并且语义类还可以支持读屏软件根据文章可以自动生成目录等等。
不过不恰当地使用语义标签反而会造成负面作用。这里我们举一个常见的误区作为例子。我们都知道ul是无序列表ol是有序列表所以很多接触过语义这个概念半懂不懂的前端工程师特别喜欢给所有并列关系的元素都套上ul。
实际上, ul 是长成下面的这种样子的(以下来自HTML标准)。
I have lived in the following countries:
* Switzerland
* Norway
* United Kingdom
* United States
ul多数出现正在行文中间它的上文多数在提示要列举某些项。但是如果所有并列关系都用ul会造成大量冗余标签。
错误地使用语义标签会给机器阅读造成混淆、增加嵌套给CSS编写加重负担。
所以,对于语义标签,**我的态度是:“用对”比“不用”好,“不用”比“用错”好。当然了,我觉得有理想的前端工程师还是应该去追求“用对”它们。**
* * *
与JavaScript这样严格的编程语言相比HTML中语义标签的使用更接近我们平常说话用的自然语言。我们说话并没有唯一的标准措辞语义标签的使用也是一样。下面我挑选了几种我认为比较重要的语义标签使用场景来为你介绍一下。
## 作为自然语言延伸的语义类标签
其实语义问题不仅仅属于理科,它还是个文科问题。
**所以我们这里讲语义标签的使用的第一个场景,也是最自然的使用场景,就是:作为自然语言和纯文本的补充,用来表达一定的结构或者消除歧义。**
我们先来看看“表达一定的结构”这个场景。
在日语中有一个语法现象叫做ルビ它的读音是ruby著名的ruby语言就是据此命名的它中文的意思大约类似于注音或者意思的注解它的形式可以看下图
![](https://static001.geekbang.org/resource/image/d4/45/d464f16955d1629b9911699e99d03f45.png)
图中的例子选自动画片《某科学的超电磁炮》第二季第一话。图中把teleport放在空间移动上方的用法就是日文中ruby的用法。“空间移动”是动画中白井黑子的技能这里动画字幕上写的是“空间移动”动画里的台词则用了英文发音“Teleport”这里就形成了一个使用ruby的场景。
ruby的这个形式在中国的网友中间最近被玩出了新花样比如表情包。
![](https://static001.geekbang.org/resource/image/67/15/67e0027f9a35eac8170b758f420ff815.jpeg)
有时候微信聊天不能用ruby这样的东西真的是好急啊只好用括号代替效果真是差了不少。
在HTML5中就引入了这个表示ruby的标签它由ruby、rt、rp三个标签来实现。
所以说这些情况里存在的语义其实原本就存在了只是我们用纯文字是没法表达的HTML作为一种“超文本”语言支持这些文字表达就是必要的了。
**还有一种情况是HTML的有些标签实际上就是必要的甚至必要的程度可以达到如果没有这个标签文字会产生歧义的程度。**
这里我们可以介绍一下em标签。
```
今天我吃了一个苹果.
```
我们看看这句话,看上去它很清楚,但是实际上,这句话放到不同上下文中,可能表达完全不同的意思。
```
昨天我吃了一个香蕉。
今天我吃了一个苹果。
```
再比如:
```
昨天我吃了两个苹果。
今天我吃了一个苹果。
```
试着读一读,这两段里面的“今天我吃了一个苹果”,你是不是发现读音不自觉地发生了变化?
实际上,不仅仅是读音,这里的意思也发生了变化。前一段中,表示我今天吃的是苹果,而不是别的什么东西,后一段中,则表示我今天只吃了一个苹果,没有多吃。
当没有上下文时如何消除歧义呢这就要用到我们的em标签了。em表示重音
```
今天我吃了一个<em>苹果</em>。
今天我吃了<em>一个</em>苹果。
```
通过em标签我们可以消除这样的歧义。
一些文章常常会拿em和strong做对比实际上我们只要理解了em的真正意思它和strong可谓天差地别并没有任何混淆的可能。
## 作为标题摘要的语义类标签
介绍完自然语言的语义场景后,我想介绍的另一个语义重要使用场景,就是文章的结构。中国古代小说就形成了“章-回”的概念,西方的戏剧也有幕的区分,所以人类的自然语言作品也是如出一辙。
HTML也应该支持这样的需求。HTML语义标签中有不少是用于支持这样的结构的标签。
语义化的HTML能够支持自动生成目录结构HTML标准中还专门规定了生成目录结构的算法即使我们并不打算深入实践语义也应该尽量在大的层面上保证这些元素的语义化使用。
首先我们需要形成一个概念一篇文档会有一个树形的目录结构它由各个级别的标题组成。这个树形结构可能不会跟HTML元素的嵌套关系一致。
```
例如:
<h1>HTML语义</h1>
<p>balah balah balah balah</p>
<h2>弱语义</h2>
<p>balah balah</p>
<h2>结构性元素</h2>
<p>balah balah</p>
......
```
这段HTML几乎是平铺的元素但是它的标题结构是
* HTML语义
* 弱语义
* 结构性元素
* ……
h1-h6是最基本的标题它们表示了文章中不同层级的标题。有些时候我们会有副标题为了避免副标题产生额外的一个层级我们使用hgroup标签。
我们来看下有/无hgroup的对比
```
<h1>JavaScript对象</h1>
<h2>我们需要模拟类吗?</h2>
<p>balah balah</p>
......
```
此段生成以下标题结构:
* JavaScript对象
* 我们需要模拟类吗?
*
```
<hgroup>
<h1>JavaScript对象</h1>
<h2>我们需要模拟类吗?</h2>
</hgroup>
<p>balah balah</p>
......
```
这一段生成以下标题结构:
* JavaScript对象——我们需要模拟类吗
*
我们通过两个效果的对比就可以知道在hgroup中的h1-h6被视为同一标题的不同组成部分。
从HTML 5开始我们有了section标签这个标签可不仅仅是一个“有语义的div”它会改变h1-h6的语义。section的嵌套会使得其中的h1-h6下降一级因此在HTML5以后我们只需要section和h1就足以形成文档的树形结构
```
<section>
<h1>HTML语义</h1>
<p>balah balah balah balah</p>
<section>
<h1>弱语义</h1>
<p>balah balah</p>
</section>
<section>
<h1>结构性元素</h1>
<p>balah balah</p>
</section>
......
</section>
```
这段代码同样会形成前面例子的标题结构:
* HTML语义
* 弱语义
* 结构性元素
* ……
## 作为整体结构的语义类标签
我们想介绍的最后一个场景是随着越来越多的浏览器推出“阅读模式”以及各种非浏览器终端的出现语义化的HTML适合机器阅读的特性变得越来越重要。
应用了语义化结构的页面,可以明确地提示出页面信息的主次关系,它能让浏览器很好地支持“阅读视图功能”,还可以让搜索引擎的命中率提升,同时,它也对视障用户的读屏软件更友好。
我们正确使用整体结构类的语义标签可以让页面对机器更友好。比如这里一个典型的body类似这样
```
<body>
<header>
<nav>
……
</nav>
</header>
<aside>
<nav>
……
</nav>
</aside>
<section>……</section>
<section>……</section>
<section>……</section>
<footer>
<address>……</address>
</footer>
</body>
```
在body下面有一个headerheader里面是一个nav跟header同级的有一个asideaside里面也有一个nav。接下来是文章的整体也就是一个一个的section。section里面可能还有嵌套但是我们就不管了最后是一个footer这个footer里面可能有address这样的内容。
除此之外还有articlearticle是一种特别的结构它表示具有一定独立性质的文章。所以article和body具有相似的结构同时一个HTML页面中可能有多个article存在。
一个典型的场景是多篇新闻展示在同一个新闻专题页面中这种类似报纸的多文章结构适合用article来组织。
```
<body>
<header>……</header>
<article>
<header>……</header>
<section>……</section>
<section>……</section>
<section>……</section>
<footer>……</footer>
</article>
<article>
……
</article>
<article>
……
</article>
<footer>
<address></address>
</footer>
</body>
```
body里面有自己的header和footer然后里面是竖篇的article每一个article里面都有自己的header、section、footer。这是一个典型的多文章结构。
在这个结构里,我们看到了一些新标签,我也来逐个介绍一下。
* header如其名通常出现在前部表示导航或者介绍性的内容。
* footer通常出现在尾部包含一些作者信息、相关链接、版权信息等。
header和footer一般都是放在article或者body的直接子元素但是标准中并没有明确规定footer也可以和asidenavsection相关联header不存在关联问题
* aside表示跟文章主体不那么相关的部分它可能包含导航、广告等工具性质的内容。
aside很容易被理解为侧边栏实际上二者是包含关系侧边栏是asideaside不一定是侧边栏。
aside和header中都可能出现导航nav标签二者的区别是header中的导航多数是到文章自己的目录而aside中的导航多数是到关联页面或者是整站地图。
最后footer中包含address这是个非常容易被误用的标签。address并非像date一样表示一个给机器阅读的地址而是表示“文章作者的联系方式”address明确地只关联到article和body。
## 总结
本篇中我们介绍了一些基本原则和HTML文档的整体结构从整体上了解了HTML语义。
至此,我们可以回答是否要语义化的问题:我们应该分开一些场景来看语义,把它用在合适的场景下,可以获得额外的效果。本篇文中,我们至少涉及了三个明确的场景:
* 自然语言表达能力的补充;
* 文章标题摘要;
* 适合机器阅读的整体结构。
下一篇中,我们会继续深入到更细致的结构中,进一步了解语义。你在工作中是否在使用语义化的标签开发?学习过本篇之后,答案有没有变化呢?你可以给我留言,我们一起讨论。
# 猜你喜欢
[![unpreview](https://static001.geekbang.org/resource/image/1a/08/1a49758821bdbdf6f0a8a1dc5bf39f08.jpg)](https://time.geekbang.org/course/intro/163?utm_term=zeusMTA7L&utm_source=app&utm_medium=chongxueqianduan&utm_campaign=163-presell)