CSS content新的替换元素规范行为解读

这篇文章发布于 2021年10月8日,星期五,20:42,归类于 CSS相关。 阅读 15290 次, 今日 2 次 2 条评论

 

CSS content占位图

一、普通元素能否变成替换元素

我们通常所说的替换元素指的是图片、视频等元素,对应的 HTML 标签是 <img><video>、而平常用来布局的 <div><p><span> 等元素都是非替换元素。

实际上,从2019年往后,上面这条规则已经变得不准确的,或者说是在约束条件下才能成立的规则。

换句话说,<div><span> 等元素在某些条件下也是可以转变成替换元素的,这个转变的条件就是 content 属性的 url() 函数语法。

二、content 与替换元素

所谓“替换元素”指的就是内容可替换,而 content 属性是可以直接替换 HTML 中的内容的,因此,可以让 content 属性生效的场景,我们都可以称为替换元素。

如果是在 ::before/::after 伪元素中生效,那么此时这个伪元素被称之为 “匿名替换元素”。

.some::before {
    content: url(1.jpg);    
}

在 CSS 语系中,没有明确的 HTML 标签的东西称之为“匿名”,例如下面这段 HTML:

<p>我是<span>鑫旭</span>

其中,“我是”的就是匿名内联盒子,而“鑫旭”是内联盒子,因为外部有明确的 <span> 标签。

在伪元素这里也是类似的,::before/::after 创建的内容外部是没有明确的标签的,因此,被称为 “匿名替换元素”。

既然 content 属性有“匿名替换元素”,那 content 属性有没有“替换元素”呢?两者的区别又是在哪里呢?

首先第一个问题的回答是 “有!”

content 新的规范特性

这个新的规范特性就是,即使不借助伪元素,content 属性也能对内容进行替换!

其历史发展进程是这样的:

  1. 没有任何浏览器支持在非伪元素中使用 content 属性;
  2. 大概17年还是18年的时候,Chrome 浏览器率先支持普通元素直接设置 content 属性;
  3. 19 年 content 规范进行了明确,Firefox 和 Safari 浏览器也跟进了支持。

因此,目前的状况是,所有现代浏览器均支持 content 属性替换内容,不过,仅支持 url() 资源替换,并不支持字符内容的替换。

举个例子,下面是个 logo 所在的 HTML:

<h1>鑫空间-鑫生活</h1>

在过去,我们的做法是设置字号为 0 或者文字透明,然后 logo 作为背景图显示,现在,可以直接使用 content 属性一次性解决:

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

url()替换元素生效示意

此时无论是辅助设备识别还是搜索引擎,都能获得准确的文字内容,而对于正常用户,看到的还是 logo 图像,兼顾了视觉与功能。

此时的 <h1> 就是一个替换元素,本质上和 <img> 元素并无区别。

和匿名替换元素区别

由于匿名替换元素缺少明确的标签,因此,图像的外部尺寸是无法进行调整的,例如:

h1::before {
    width: 100px; height: 100px;
    content: url(logo.png);    
}

上面的 CSS 中的 width:100pxheight:100px; 都是无法改变 logo.png 这个图像的尺寸的,因为他是“匿名”的,这就好像一个没有蛋壳的鸡蛋,你无法通过改变蛋壳大小,从而影响内部蛋白和淡黄的形状和尺寸。

但是替换元素不同,由于有显式的标签元素,因此,可以作为替换元素的外部尺寸进行设置,例如:

h1 {
    width: 100px; height: 100px;
    content: url(logo.png);    
}

此时 logo.png 图像的尺寸就是 100px * 100px。

三、content 新特性解读

所有现代浏览器均支持在任意 HTML 元素中使用 content url() 函数语法,且一旦使用,该元素就会变成替换元素。

原因在于:

  1. 从行为上讲,原本的内容全部被替换成了图像,是典型的替换元素。
  2. 从样式表现上将,和 <img> 元素并无二样。

<img> 元素并无区别

例如,<img> 元素通过设置宽高可以拉伸图片的尺寸,在上面的例子中 <h1> 元素也有类型的行为。

又例如,<img> 元素通过设置 object-fit 属性控制图像的如何适应显示,<h1> 元素也有一样的行为,例如:

h1 {
    width: 100px; height: 100px;
    content: url(logo.png);
    object-fit: contain;
}

就是下图所示的效果,logo 图像在保持比例的同时,显示在了 100px * 100px 的区域内。

object-fit作用于非图像元素

四、反之也成立

所谓反之也成立,指的是,如果原本一个元素是替换元素,那么如果我们设置 content:'' 进行重置,则这个元素会被还原成非替换元素。

此时,我们就可以使用 ::before / ::after 伪元素实现一些功能。

例如,2020年最热门的“图片加载失败后CSS样式处理最佳实践”这篇文章提到的技术实现,就是利用这一特性:

<img src="zxx.png" alt="CSS新世界封面" onerror="this.classList.add('error');">
img.error {
  display: inline-block;
  transform: scale(1);
  content: '';
  color: transparent;
}
img.error::before {
  content: '';
  position: absolute;
  left: 0; top: 0;
  width: 100%; height: 100%;
  background: #f5f5f5 url(break.svg) no-repeat center / 50% 50%;
}
img.error::after {
  content: attr(alt);
  //... 略
}

此时,出错的图片不仅显示了裂开的图像,同时还显示了 alt 信息,让用户知道这张图片所代表的含义是什么。

图像失败和alt信息同时出现

五、实际开发中的应用

使用 content 属性显示图像在日常开发中并不常用,如果是普通的图像显示,你就使用 <img> 元素,如果是装饰性的图像显示,你就使用 background-image 属性。

只有什么时候需要使用 content 属性呢?

就是希望源代码层面还是原来的 HTML 内容结构,但是视觉表现上依然是图像。

比方说一开始提到的logo显示,又比如想要在不改变 HTML 结构的前提下,清空(或隐藏)一大段内容,则可以使用:

.container {
    content: url();    
}

不占据任何空间,同时依然可以响应点击行为,能够被屏幕阅读器等设备识别。

好,以上就是本文的全部内容,带大家了解了下 content 属性新的行为表现。

如果本文的内容对您的学习有所帮助,欢迎转发,欢迎分享。

(本篇完)

分享到:


发表评论(目前2 条评论)

  1. DeathGhost说道:

    “从而影响内部蛋白和淡黄” — 蛋黄 — lol

  2. neo说道:

    等大佬开发奇妙用法