<!-- 《CSS世界》 张鑫旭著 -->
替换元素
根据是否具有可替换内容,我们可以把元素分为替换元素和非替换元素。
<img>、<object>、<video>、<iframe>或表单元素<textarea>和<input>都是典型的替换元素。
替换元素除了内容可替换这一特性之外,还有以下一些特性:
(1)内容的外观不受页面上的CSS的影响。用专业的话讲就是样式表现在CSS作用域之外。例如:直接 input[type='checkbox'] {} 无法更改内间距、背景色等样式,需要用浏览器自身暴露的一些样式接口,例如::-ms-check {} 可以更改高版本IE浏览器下单复选框的内间距、背景色等样式
(2)有自己的尺寸。在WEB中,很多替换元素在没有明确尺寸设定的情况下,其默认的尺寸(不包括边框)是300像素 × 150像素,如<video>、<iframe>或者<canvas>等,也有少部分替换元素为0像素,如<img>图片,而表单元素的替换元素尺寸则和浏览器有关,没有明显的规律。
(3)在很多CSS属性上都有自己的一套表现规则。比较有代表性的是vertical-align属性,对于替换元素和非替换元素,vertical-align属性值的解释是不一样的。比方说vertical-align的默认值的baseline,很简单的属性值,基线之意,被定义为字符x的下边缘,在西方语言体系里近乎常识,几乎无人不知,但是到了替换元素那里就不适用了。为什么呢?因为替换元素的内容往往不可能含有字符x,于是替换元素的基线就被硬生生定义成了元素的下边缘。
替换元素的默认display值
替换元素都是内联水平元素,但是替换元素的display值却是不一样的,并且在不同浏览器的值也是不一样的,但是这并不会影响替换元素的尺寸计算规则,所以深究替换元素的display值是没有意义的。
<input type="button" value="按钮"> <button type="button">按钮</button>
<input>和<button>按钮的区别在于两种按钮默认的 white-space 值不一样,前者是 pre,后者是 normal,所表示出来的差异就是:当按钮文字足够多的时候,<input> 按钮不会自动换行,<button> 按钮会自动换行。
替换元素的尺寸计算规则
作者将替换元素的尺寸从内而外分为3类:固有尺寸、HTML尺寸和CSS尺寸。
(1)固有尺寸指的是替换内容原本的尺寸。例如:图片、视频作为一个独立文件存在时,都是有着自己的宽度和高度的。这个宽度和高度的大小就是这里的“固有尺寸”。对于表单替换元素,“固有尺寸”可以理解为“不加修饰的默认尺寸”。
(2)HTML 尺寸只能通过 HTML 原生属性改变,包括<img>的width和height属性、<input>的size属性,<textarea>的cols和rows属性等。
(3)CSS 尺寸特指可以通过 CSS 的width和height或者max-width/min-width和max-height/min-height设置的尺寸,对应盒尺寸中的content box。
这3层结构的计算规则如下:
- CSS 尺寸 覆盖 HTML 尺寸, HTML 尺寸覆盖固有尺寸
- 如果固有尺寸含有固有的宽高比例,同时仅设置了宽度或者仅设置了高度,则元素按照固有的宽高比例显示。
- 如果三种尺寸都没有,则最终宽度表现为300像素,高度表现为150像素
- <img>是这其中的意外,单看规则,一个没有替换内容也没有尺寸设定的裸露的<img>元素,应该是300像素 × 150像素,结果不仅不是这个尺寸,而且各个浏览器下的尺寸还不一样。IE浏览器下是28 × 30,Chrome浏览器下是0 × 0,Firefox浏览器下是0 × 22.。尺寸不一样还不打紧,因为我们都会设置尺寸,但是关键是表现型也不一样。先看下面的例子:
web开发的时候,为了提高加载性能以及节约带宽费用,首屏一下的图片就会通过滚屏加载的方式异步加载,然后这个即将异步加载的图片为了布局稳健、体验良好,往往会使用一张透明的图片占位,例如:<img src="transparent.png">
实际上这个透明的占位图片也是多余的资源,我们可以直接:<img>,然后配合CSS实现一样的效果:
img { visibility: hidden; } img[src] { visibility: visible; }
这里的<img>直接没有src属性,因为src=""在很多浏览器下依然会有请求,而且请求的是当前页面数据。但图片的src属性缺省的时候,图片不会有任何请求,是最高效的实现方式。
但是这里存在一个问题,Firefox浏览器下,src缺省的<img>不是替换元素,而是一个普通的内联元素,所以使用的不是替换元素的尺寸规则,而是类似<span>的内联元素尺寸规则,宽高会无效。这时就要设置display: inline-block后再设置宽高了,既对Firefox浏览器有效,又不会影响其他浏览器的图片表现。
HTML 尺寸和 CSS 尺寸是怎么影响图片的尺寸的呢?
尺寸变化的本质不是改变固有尺寸,而是采用了填充作为适配 HTML 尺寸和 CSS 尺寸的方式。在 CSS3 新世界中,<img>和其他一些替换元素的替换内容的适配方式可以通过object-fit属性(IE全部不兼容)修改,例如:<img>默认声明是:object-fit: fill,如果我们设置object-fit: none,则我们图片的尺寸就完全不受控制(据笔者测试,是保持比例不变,不缩放,但是尺寸是受css属性width和height限制的);如果我们设置object-fit: contain,则图片会以保持比例,并尽可能利用 HTML 尺寸但又不会超出的方式显示。