1. content 与替换元素
替换元素(<img>
<object>
<video>
<iframe>
或表单元素如 <textarea>
<input>
<select>
),顾名思义,内容可替换,其他特性:
-
替换元素的外观不受 css 的影响。如何改变替换元素的外观,需要类似 appearence 属性,或浏览器自身暴露的一些样式接口,如
::-ms-check{}
可更改高版本 IE 浏览器下单复选框的内间距、背景色等样式,但直接input[type="checkbox"]{}
却无法更改。 -
有自己的尺寸。很多替换元素在没有明确尺寸设定的情况下,其默认的尺寸(不包括边框)是
300px * 150px
,如 video、iframe、canvas 查看case,也有少部分替换元素为0px
,如 img。而表单元素的替换元素的尺寸与浏览器有关,没有明显的规律。 -
在很多 css 属性上有自己的一套表现规则。比如
vertical-align
属性,对于非替换元素,默认值是baseline
,即 x 字符的下边缘,替换元素的内容没有 x 字符,于是基线被定义成了元素的下边缘。
2. 替换元素尺寸计算
css > html > 固有尺寸
- 如果固有尺寸具有固有的宽高比例,同时仅设置了高度或宽度,则元素按固有的宽高比例显示。
- 内联替换元素和块级替换元素使用同一套计算规则。
如:case
虽然图片变成了块级,但是尺寸规则还是和内联状态下一致。这也是为何图片及其他表单类替换元素设置img {display: block;} <img src="1.jpg"/>
display:block
宽度却没有 100% 容器的原因。 - 图片的 content 替换内容默认的适配方式是
object-fit: fill
,其他属性object-fit:none
object-fit:contain
case
3. 替换元素与非替换元素之间的关系
- 相差一个
src
查看demo - 相差一个
content
demo1 使用 content 属性生成一张图片。 Chrome 下,所有的元素都支持 content 属性,而其他浏览器仅在::before/::after
伪元素下支持。
demo2 使用 content 属性替换将图片为另一张图片。content 属性改变的仅是视觉呈现,当右键保存的时候,仍是保存的 src 对应的图片。
demo3 让普通标签元素变成替换元素。视觉上文字被替换了,但屏幕阅读器阅读的还是文字内容,搜索引擎抓取的还是文本信息,对页面的可访问性没有任何影响。想在移动端使用该技术,建议使用 SVG 矢量图片。 - content 属性生成的内容被称为“匿名替换元素”。
- content 生成的文本无法选中、无法复制,好像设置了
user-select:none
,同时,无法被屏幕阅读设备读取、无法被搜索引擎抓取。 - 不能左右
:empty
伪类。case - content 动态生成值无法获取。
- content 生成的文本无法选中、无法复制,好像设置了
4. content 内容生成技术
在实际项目中,content 属性几乎都用在 ::before/::after
这俩个伪元素中,因此,“content 内容生成技术”有时候也称为“::before/::after
伪元素技术”。
4.1 content 辅助元素生成
此应用的核心不在 content 生成的内容,而在于伪元素本身,通常,会把 content 设置为空字符串。
.element::before {
content: '';
}
然后,利用其它 css 代码来生成辅助元素,或实现图形效果,或实现特定布局。
还有一个常见应用,清除浮动带来的影响:
.clear::after {
content: '';
display: table; /* or block */
clear: both;
}
// div 与第一个 i 之间不能换行
<div id="box" class="box"><i class="bar"></i>
<i class="bar"></i>
<i class="bar"></i>
<i class="bar"></i>
</div>
.box {
width: 256px;
height: 256px;
border-bottom: 1px dashed #ccc;
text-align: justify;
background-color: #f9f9f9;
}
.bar {
display: inline-block;
width: 20px; height: 0;
}
/* 底对齐 */
.box:before {
content: "";
display: inline-block;
height: 100%;
}
/* 两端对齐 */
.box:after {
content: "";
display: inline-block;
width: 100%;
}
4.2 content 字符内容生成
比如配合 @font-face
规则实现图标字体效果 demo
除了 content 内容为常规字符,还可以插入 Unicode 字符,比较经典的是插入换行符来实现某些布局或效果。
::after {
content: '\A';
white-space: pre;
}
'\A'
:换行符中的 LF 字符,其 Unicode 编码是 000A,在 content 中直接写作 '\A'
'\D'
:换行符中的 CR 字符,其 Unicode 编码是 000D。
实例:实现动态 ...
加载效果 case
正在加载中<dot>...</dot>
dot {
display: inline-block;
height: 1em;
line-height: 1;
text-align: left;
vertical-align: -.25em;
overflow: hidden;
}
dot::before {
display: block;
content: '...\A..\A.';
white-space: pre-wrap;
animation: dot 3s infinite step-start both;
}
@keyframes dot {
33% { transform: translateY(-2em); }
66% { transform: translateY(-1em); }
}
实现原理:插入 3 行内容,分别是 3 个点、2 个点和 1 个点,然后通过 transfrom 控制垂直位置,依次展示每行内容。
伪元素使用 ::before
同时 display 设置为 block,是为了在高版本浏览器下原来的 3 个点推到最下面,不会影响 content 的 3 行内容显示,使用 ::after
恐怕就很难实现。
4.3 content 图片生成
content 图片生成指的是直接使用 URL 功能符显示图片,URL 中的地址可以是常见的 png、jpg 格式,也可以是 ico 图片、svg 文件和 base64URL 地址,但不支持 css3 渐变背景图。
div::before {
content: url(1.jpg);
}
4.4 content 开启闭合符合生成
css 中有个 quotes
属性,可以指定 open-quote
close-quote
具体是什么。
case 针对不同语言指定不同的前后符号。
<p lang="ch"><q>中文</q></p>
<p lang="en"><q>This book is very good!</q></p>
<p lang="no"><q>denne bog er fantastisk!</q></p>
:lang(ch) > q {
quotes: '“' '”';
}
:lang(en) > q {
quotes: '"' '"';
}
:lang(no) > q {
quotes: '<' '>';
}
case “提问、回答”
4.5 content attr 属性值内容生成
img::after {
content: attr(alt);
}
.icon::before {
content: attr(data-title); /* 自定义属性 */
}
4.6 content 计数器
计数器两个属性:counter-reset
counter-increment
一个方法:counter()/counters()
-
counter-reset
:计数器-重置,给计数器命名,顺便告诉从哪个数字开始计数,默认是 0. demo
.xxx {
counter-reset: name 3; /* 从 3 开始计数*/
}
.xxx::before {
content: counter(name);
}
多个计数器 demo
.xxx {
counter-reset: name1 3 name2 4; /* name1 从 3 开始计数, name2 从 4 开始*/
}
.xxx::before {
content: counter(name1);
}
.xxx::after {
content: counter(name2);
}
counter-reset
还可以设置为 none 和 inherit,取消重置以及继承重置。
-
counter-increment
:计数器递增,值为counter-reset
的 1 个或多个关键字,后面可以跟随数字,表示每次计数的变化值。缺省为 1。
counter-increment
一旦出现,会在counter-reset
初始值上增加。counter()
负责输出。 -
counter()
显示计数。
counter(name)
counter(name, style)
style
即为 list-style-type
支持的值,作用是:我们递增递减的可以不一定是数字,还可以是英文字母或罗马文等。demo
counter()
支持级联。demo
-
counters()
:嵌套计数
counters(name, style)
style 参数为字符串(需要引号包围,必需参数),表示子序号的连接字符串。例如,1.1
的 string 就是 .
,1-1
的 string 就是 -
。
要实现嵌套,必须让每个列表容器拥有一个 counter-reset
,通过子辈对父辈的 counter-reset
重置、配合 counters()
方法实现。
demo
<div class="reset">
<div class="counter">我是王小二
<div class="reset">
<div class="counter">我是王小二的大儿子</div>
<div class="counter">我是王小二的二儿子
<div class="reset">
<div class="counter">我是王小二的二儿子的大孙子</div>
<div class="counter">我是王小二的二儿子的二孙子</div>
<div class="counter">我是王小二的二儿子的小孙子</div>
</div>
</div>
<div class="counter">我是王小二的三儿子</div>
</div>
</div>
<div class="counter">我是王小三</div>
<div class="counter">我是王小四
<div class="reset">
<div class="counter">我是王小四的大儿子</div>
</div>
</div>
</div>
.reset {
padding-left: 20px;
counter-reset: wangxiaoer;
}
.counter::before {
content: counters(wangxiaoer, '-') '. ';
counter-increment: wangxiaoer;
}
显示 content 计数值的那个 DOM 元素在文档流中的位置一定要在 counter-increment
元素后面,否则没有计数效果。
4.7 content 内容生成的混合特性
是指 content 内容生成语法可以混合在一起使用
a::after {
content: "(" attr(href) ")";
}
q::before {
content: open-quote url(1.jpg);
}
.counter::before {
content: counters(name, '-') '. ';
}