深入理解替换元素——《CSS世界》读书笔记

390 阅读5分钟

前言

本篇文章是我阅读《CSS世界》中的第四章关于替换元素部分的读书笔记,我将尽量用精炼的文字总结替换元素的相关概念。如有不解之处,或有可能是我的文字有所疏漏,还请翻阅《CSS世界》一书。

1. 什么是替换元素

根据“外在盒子”是内联还是块级我们可以把元素分为内联元素和块级元素,而根据是否具有可替换内容,我们也可以把元素分为替换元素和非替换元素。

通过修改某个属性值,呈现的内容可以被替换的元素称为“替换元素”。这个内容就是 margin、border、padding 和 content 这4个盒子中的 content box。

<img><object><video><iframe> 或者表单元素 <textarea><input> 都是典型的替换元素。

替换元素除了内容可替换外,还具有以下特性:

  1. 内容的外观不受页面上的 CSS 的影响

  2. 有自己的默认尺寸

    • 默认的尺寸是 300×150 像素:如 <video><iframe> 或者 <canvas> 等。
    • 默认的尺寸是 0:如 <img>
    • 表单元素的替换元素的尺寸和浏览器有关,没有明显的规律。
  3. 在很多 CSS 属性上有自己的一套表现规则

    例如 vertical-align 属性的默认值的 baseline,对于非替换元素,基线被定义为字符 x 的 下边缘。替换元素的基线定义为元素的下边缘。

举例:<select> 是替换元素。首先,内容可替换;其次,基本样式外部 CSS 很难改变;最后,它有自己的尺寸,基线也是下边缘等。

2. 替换元素的默认 display 值

各个替换元素的默认 display 属性值:

元素ChromeFirefoxIE
<img>inlineinlineinline
<iframe>inlineinlineinline
<video>inlineinlineinline
<select>inline-blockinline-blockinline-block
<input>inline-blockinlineinline-block
range|file <input>inline-blockinline-blockinline-block
hidden <input>nonenonenone
<button>inline-blockinline-blockinline-block
<textarea>inline-blockinlineinline-block

对于替换元素的 displayinlineblockinline-block 中的任意一个,其尺寸计算规则都是一样的。

3. 替换元素的尺寸计算规则

替换元素的尺寸从内而外分为 3 类:

  • 固有尺寸

    指的是替换内容原本的尺寸。例如图片、视频作为一个独立文件存在的时候,都是有着自己的宽度和高度的。

  • HTML 尺寸

    HTML 原生属性包括 <img>widthheight 属性、<input>size 属性、<textarea>colsrows 属性等。

    <img width="300" height="100">
    <input type="file" size="30">
    <textarea cols="20" rows="5></textarea>
    
  • CSS 尺寸

    特指可以通过 CSS 的 widthheight 或者 max-width/min-widthmax-height/min-height 设置的尺寸,对应盒尺寸中的 content-box。

3 层结构的计算规则:

  1. 没有 CSS 尺寸和 HTML 尺寸,则使用固有尺寸作为最终的宽高
  2. 没有 CSS 尺寸,则使用 HTML 尺寸作为最终的宽高
  3. 有 CSS 尺寸,则最终尺寸由 CSS 属性决定
  4. “固有尺寸”含有固有的宽高比例,同时仅设置宽度或高度,元素依然按照固有的宽高比例显示
  5. 上面的条件都不符合,则使用替换元素的默认尺寸

替换元素的内容尺寸变化的本质并不是改变了固有尺寸,而是由于默认采用了 object-fit: fill 作为替换元素内容适配 HTML 尺寸和 CSS 尺寸的方式

4. 替换元素和非替换元素的距离有多远

观点一:替换元素和非替换元素之间只隔了一个 src 属性

如果我们把 src 属性去掉,<img> 其实就是一个和 <span> 类似的普通的内联标签,也就是成了一个非替换元素。

  • Firefox 浏览器不需要额外条件
  • Chrome 浏览器需要特定的条件触发,需要有不为空的 alt 属性值
  • IE 浏览器中有个默认的占位替换内容,当 src 属性缺失的时候,会使用这个默认的占位内容,而不是原本的 <img> 元素

由于没有 src 属性的 <img> 是非替换元素,这时可以对它使用伪元素,而一旦加上 src 属性,变为替换元素后伪元素就失效。利用这点,在 ::before::after 中设置图片还没加载时的信息展示,等图片加载完,添加 src 属性,清除伪元素的展示效果。

观点二:替换元素和非替换元素之间只隔了一个 content 属性

替换元素之所以为替换元素,就是因为其内容可替换,而这个内容就是 margin、border、padding 和 content 这4个盒子中的 content box,对应的CSS属性是 content

  1. 没有 src 属性的 <img> 是非替换元素,但是,如果我们此时使用 content 属性给它生成一张图片,它又变为一个替换元素。

    <style>
    img {
      content: url(1.jpg);
    }
    </style>
    
    <img>
    
  2. 如果图片原来是有 src 地址的,也可以使用 content 属性把图片内容给置换掉。

    <style>
    img:hover {
      content: url(laugh-tear.png);
    }
    </style>
    
    <img src="laugh.png">
    

    content 属性改变的仅仅是视觉呈现,当我们以右键或其他形式保存这张图片的时候,所保存的还是原来 src 对应的图片。

  3. 使用 content 属性,还可以让普通标签元素变成替换元素

    官网的标志为了SEO优化往往都会使用 <h1> 标签,里面会有网站名称,标志图片被作为背景图:

    h1 {
      width: 180px;
      height: 36px;
      background: url(logo.png);
      text-indent: -999px; /* 隐藏文字 */
    }
    

    可以利用 content 属性,<h1> 变成了替换元素,尺寸规则就是替换元素的尺寸规则,完美适应原始图片大小。虽然视觉上文字被替换了,但是屏幕阅读设备和搜索引擎SEO抓取的还是原始的文本信息。

    h1 {
      content: url(logo.png);
    }
    

5. content 与替换元素关系剖析

content 属性生成的对象称为“匿名替换元素”(anonymous replaced element),实际上:content 属性生成的内容都是替换元素。

举例:

  1. 使用 content 生成的文本是无法选中、无法复制的,同时,content 生成的文本无法被屏幕阅读设备读取,也无法被搜索引擎抓取。

  2. 不能左右 :empty 伪类。

  3. content 动态生成值无法获取。

.total::after {
  content: counter(icecream);
}