看似普通的元素的背后
2、重新认识列表元素
2.1、无序列表元素除<ul>外还有其他的
一提到无序列表,大家的第一反应一定是<ul>元素,实际上,在HTML众多元素中,还有一个元素也能扮演无序列表的角色,那就是<menu>元素。
<menu>元素可以看成是<ul>元素的平行替代,两者的语法及默认样式都是一致的,区别在于语义上。
<menu>元素用在可交互的列表上,而<ul>元素用在称述性的列表上。
有一个很简单的原则可以用来判断是该用<menu>还是该用<ul>,即如果<li>列表中就是链接元素或按钮元素,则使用<menu>,否则就使用<ul>元素,下面举几个例子。


所以,大家不妨看看自己手头上的项目,在无序列表的使用上,是不是还有语义不到位的问题。
2.2、
-
元素额外支持的那些属性
我们可能使用过如下所示的CSS代码来改变<ol>元素的序号类型,比如重置默认的阿拉伯数字序号为大写英文字母。

此时,下面这段HTML代码的呈现效果就会如图所示。


那么请问,如果我希望有序列表的序号不是从1或者A开始的,而是从3或者C开始的,该如何实现呢?或者说你有办法让有序列表的序号倒序排列吗?
要回答这两个问题,就不得不说一说在众多列表元素中,只有<ol>元素才支持的几个属性了。
2.2.1、type属性
<ol>列表支持type属性,可以用来定义有序列表的类型,跟CSS中的list-style-type属性值有一一对应的关系,详见下表。

当HTML中的type和CSS中的list-style-type同时出现的时候,list-style-type会优先于type,即显示list-style-type对应值内容。如果CSS中未设置具体的list-style-type值,自然以type属性的设置为准。
有人可能会问,既然有了CSS的list-style-type属性,那么<ol>元素上的type属性是不是就无用武之地呢?
其实不然,type属性相比list-style-type有两个不太突出的优点:
- 更容易记忆,例如同样是设置列表序号为大写字母,type属性设置为A就好,而list-style-type的值则是upper-alpha,显然后者更难记忆。
- 语义化,有助于机器识别准确的序号类型,尤其是当多个有序列表相互嵌套的时候。
因此,我的建议是,如果可以,优先使用HTML type属性设置有序符号的类型。
2.2.2、start和value属性
start和value属性可以指定有序列表的起始序号,其中,start属性是用在<ol>元素上的,而value属性是用在<li>元素上的,使用示意参见如下代码。


上面两种写法都可以渲染出如图所示的列表效果。

如果同时设置start和value属性,则以value属性为准。
另外,如果是字母排序,且序号范围超过了26,则会在前面叠加字母作为前缀,例如:

此时的效果如图所示,可以看到,所有字母的前面都有一个共同的字母A。

2.2.3、reversed降序
严格来讲,reversed是个新属性,它出现的时间和浏览器全面支持Flex布局的时期一致,因此,IE浏览器并不支持它。
该属性可以在不改变列表元素布局的情况下,让有序列表的序号按照倒序呈现。例如:

此时,列表的序号就会从3开始,依次递减,如图所示。

基本上这种有序列表的倒序排列使用的都是这里的reversed属性,简单快捷,尽量不要使用CSS在布局层面强制倒序,也就是尽量不要使用下面的CSS代码,除非在有序符号使用CSS计数器实现的场景。

以上几个属性就是
- 元素才有的HTML属性,每个属性都有其独到的作用,遇到符合的场景一定要优先使用,而不是借助CSS或者JavaScript代码,因为可以收获很多看不见的好处。举个非常简单的例子,在复制页面内容并粘贴到富文本编辑器的场景中,如果有序列表的起始值或者反序都是使用CSS代码模拟的,那么,当粘贴到富文本编辑器中的时候,这些信息就会丢失,而如果使用HTML属性,这些信息都会被保留到富文本编辑器中。
2.3、定义列表的特点
在HTML中,提到定义列表,通常指的就是<dl>、<dt>和<dd>这三个元素。
其中的首字母’d’是按照definition来理解的,表示定义;'l’是list的首字母,表示列表;'t’是term的首字母,表示术语;'d’是description的首字母,表示描述。
相比于无序列表和有序列表,定义列表有个非常显著的特点—自由。
自由在于<dl>元素可以包含任意数量的<dt>和<dd>元素,可以和几乎任意的块级元素相邻或嵌套。
先看数量任意的案例。
- (1)一个术语对应一个描述

- (2)一个术语对应多个描述


- (3)多个术语对应一个描述

再看一下和其他元素相邻或嵌套的案例。 - (1)与<p>元素相邻

- (2)使用<div>元素嵌套

以上用法都是合法的,但如果是<li>列表,那么无论是相邻还是嵌套,均不推荐使用,因为在部分浏览器下,例如非Chromium的Edge浏览器下,列表的序号显示就会出现异常。
语义的使用
定义列表非常适合用在对术语进行定义和解释的场景中,例如技术文档的语法和参数的罗列与说明。
在日常开发中,我们还可以适当拓展定义列表的使用范围,也就是带有标签的列表也可以使用<dl>元素。
例如:

如果是带有标题的列表,则推荐使用<section>元素。
例如:

3、正确认识<body>元素和<html>元素
在HTML中,<body>和<html>并非两个完全独立的元素。
3.1、难以名状的关联性
先从很多人感到困惑的现象说起。
新建一个空白页面,我们不设置任何额外的CSS代码,此时,我们使用如下所示的JavaScript代码去获取<body>元素的高度,返回的结果会是0,运行结果如图所示。

但是,我们给<body>元素设置背景色,例如纯黑色背景:

此时,整个页面的背景色都变成了黑色,如图所示。

这就很奇怪了,明明<body>元素的高度是0,其背景色为何会铺满整个浏览器窗口呢?
还有更奇怪的,此时,我们给<html>元素设置任意的背景,例如线性渐变(代码参见下方),则原本<body>元素设置的黑色背景奇迹般地消失了,并且渐变背景的平铺高度只有8px,是水平条纹,效果如图所示。


有两个问题,其一,原本<body>元素的黑色背景去哪里了?其二,<html>元素的渐变背景为何是8px高度平铺?
不卖关子了,直接说结论;
- (1)如果<html>元素未设置背景,则<body>元素的背景会自动按照<html>元素的背景规则渲染,否则按照类似<div>这样的普通元素的背景规则渲染。
- <html>元素的背景高度至少为一屏。
下面按照上述结论再具体解释一下。
- 当仅给<body>元素设置背景色的时候,其渲染效果和<html>元素设置背景色一致,由于<html>元素的背景高度至少为一屏,因此背景色是铺满整个屏幕的,哪怕<body>元素的实际高度是0。
- 当<html>元素设置了渐变背景后,<body>元素的背景色按照普通的HTML元素的背景规则渲染,由于高度是0,因此黑色背景消失不可见。
- <body>元素会有margin:8px的默认样式,在CSS中有个名为“margin合并”的现象,其中的一个规则就是,如果块级元素没有任何内容,同时没有设置padding或border之类的样式,那么上下margin会合并为较大的那个值。
因此,默认状态下,<html>元素的高度是8px,所以渐变背景的屏幕高度就是8px,而<html>元素的背景至少有一屏高度,因此,可以看到8px的水平条纹铺满整个屏幕。
明白了上面的解释,自然也就可以明白下面这些现象了。
- 如果<body>元素直接设置线性渐变背景,则最终的效果也是8px高的水平条纹,代码如下所示,最终渲染效果如图所示,是黑色到天蓝色的8px高的水平条纹。


- 如果给<html>设置一个具体的高度值,例如100px,则水平条纹的平铺高度也会是100px,效果如图所示。

以上描述的现象都可以通过在浏览器中输入地址https://www.htmlapi.cn/2/3-1.html访问来体验。
失效的overflow:hidden
除背景之外,<body>元素的overflow属性也有类似的“冒泡”现象。举个例子,如下所示的HTML和CSS代码:

按照我们对现有知识的理解,<body>元素的高度只有50px,同时设置了尺寸溢出隐藏,那么里面的<div>子元素的150px高度应该只有50px的高度是可见的,但实际上overflow:hidden失效了,<div>元素并没有被隐藏。
为了方便预览,我们不妨给<body>加个黑色边框,此时的效果就会如图所示,可以看到棕色的背景色块完全暴露在眼前,高度溢出的部分并没有被隐藏。

很神奇的是,如果给<html>元素设置overflow:hidden,则溢出的<div>被隐藏了,哪怕这个<html>元素的高度远远大于<div>的高度也同样如此。

此时的<body>元素的overflow:hidden生效了,效果如图所示。

对于上述现象,可以通过在浏览器中输入地址https://www.htmlapi.cn/2/3-2.html访问来体验。
为何会这样?
其实和背景色的渲染规则有些类似,即:
- 如果<html>元素没有设置overflow属性,那么<body>元素设置的overflow属性值可以看成设置在<html>元素上;
- <html>元素的overflow属性生效高度至少为一屏。
所以,在本例中:
- 就算给<html>元素设置overflow:scroll,<body>元素的overflow:hidden也会生效。
- 如果给<div>元素设置足够高的高度,例如:

那么可以看到<div>元素超出一屏高度的区域被隐藏了,原因就是此时溢出隐藏的容器元素是<html>,而<html>元素的overflow属性的最小计算高度是一屏。
也就是说,虽然看起来<body>和<html>是两个独立的元素,但实际上,彼此之间有很多替代渲染规则,了解这种规则有助于更好地理解Web网页在窗体层面的一些渲染现象。
3.2、桌面端和移动端的差异
在桌面端,页面默认的滚动条是<html>元素产生的,而在移动端,该滚动条是<body>元素产生的。
也就是说,在桌面端网页中,我们设置如下所示的CSS代码,可以让页面窗体不产生滚动条:

但是在移动端,上面的设置是无效的,反而需要设置在<body>元素上:

这个现象也就导致一些在传统页面中运行良好的代码在移动端会有问题,例如使用JavaScript设置页面滚动到顶部,在过去,开发者可能会使用如下所示的JavaScript代码:

这就会导致一个问题,如果是响应式布局的页面,那么这段代码在移动端就会出现问题,也正是考虑到这一点,W3C官网定义了一个新的全局API—document.scrollingElement,可以返回当前页面的窗体滚动对象,此API已经在2015年开始陆续被现代浏览器支持。
至于其他一些特性,例如页面没有<body>元素的时候浏览器会自动生成<body>元素、<!DOCTYPE html>严格模式等就不展开介绍了,大家只要正常使用HTML即可,无须了解这些细节知识。
1183



被折叠的 条评论
为什么被折叠?



