什么是选择符
选择符决定它和文档树中的哪个元素相匹配,其实是模式匹配,这样它所定义的样式就能应用到那个元素上。
怎么写
选择符可以简单到只有一个元素名,如 p {},也可以复杂到很多选择符组合在一起,如 .header .title {}。那它是怎么定义的呢?CSS3 中定义:
- 选择符是一组或多组简单选择符通过连接符组合起来的
- 一组简单选择符就是多个简单选择符不是用连接符组合起来的
- 简单选择符就是最最基本的选择符,包含 通用选择符(
*)、类型选择符(p, div...)、类(.header...)、伪类(:first-child...)、ID(#footer…)、属性选择符([attr]...) - 连接符包含
space, +, > , ~
CSS3 和 CSS 2.1 有什么不同
1、对于简单选择符的定义不同CSS 2.1 定义简单选择符为一个类型或通用选择符后跟着0个或多个属性、ID、伪类选择符。
也就是说 p.name 在 CSS2 中是一个简单选择符,而在 CSS3 中则是两个简单选择符连接在一起的一个组
2、引入了更多的伪类选择符CSS3 引入了如 nth-child(), :nth-of-type(), :target(), :not()...等丰富的伪类选择符
3、伪元素的写法改为 ::
把 CSS2 中 :first-line 的写法改为了 ::first-line,即把伪元素的 : 改为了 ::,应该是要和伪类进行区分
4、引入了新的连接符 ~
这是一个通用兄弟选择符,可能是觉得 + 还不够用吧,只能选择直接相邻的兄弟
连接符
分为三种:后代(space)、子元素(>)、相邻兄弟(+)、通用兄弟(~),例如下面的demo:
|
|
相邻兄弟我常用来设置重复区块之间的间隔:
|
|
分类
- 类:
.class - ID:
#id - 通用选择符:
* - 类型选择符:
p, div, section... - 属性选择符:
[attr], [attr=val], [attr=|val], [attr=~val], [attr=^val], [attr=$val], [attr=*val] - 伪类
- 动态伪类
- 链接伪类:
:link, :visited - 用户交互:
:hover, :active, :focus - 目标:
:target - UI:
:enabled, :disabled, :checked - 结构化:
:nth-child(), :nth-last-child(), :nth-of-type(), nth-last-of-type(), :only-child, :only-of-type, :empty... - :not()
- 伪元素
::first-line::first-letter::before/::after
::before/::after
这两个伪元素功能非常强大,从 a single div这个页面就可见一斑。日常中用它画个三角形、放置一个背景图片都是很常见的:
|
|
个人很喜欢这俩,既不占用额外的 HTML 标签,又能写丰富的样式和动画
权重
我们有这么多的选择符,那如果多个选择符都匹配同一个元素时,该应用哪个呢?规范定义了一组数值 abc
- 计算
ID选择符 的个数,赋值给a - 计算 类、属性、伪类 选择符 的个数,赋值给
b - 计算 类型、伪元素选择符 的个数,赋值给
c - 忽略通用选择符
:not()不计算,但它里面的选择符还是正常计算
下面的例子中 p#footer 的权重最大:
* => 000
p => 001
p::before => 002
p#footer => 101
p.name => 011
这些是从选择符本身来看的,如果结合样式的来源(开发者、用户、浏览器)以及重要性 (!important)来看,那么一个元素最终的样式规则定义如下:
- 根据来源、重要性排序
- 浏览器默认样式
- 开发者定义的普通样式
- 用户定义的普通样式
- 用户定义的重要样式(
!important) - 开发者定义的重要样式(
!important)
- 相同重要性、来源的再根据选择符本身的权重抉择,越具体权重越大
- 前面计算的结果都一样的话,后来者居上
从上面的定义可以看到虽然用户可以覆盖开发者样式,但是 !important 赋予了开发者更高的权利,从而可以提高页面易访问性,避免用户瞎写导致页面布局错乱
属性值的计算
一旦用户代理解析完文档并构建了一个文档树,那么就需要为每个元素赋予其相应的属性值如 border, color 等。那么这个属性值是如何计算的呢?根据规范,最终的属性是通过下面4个步骤计算得到的:
- 规范规定的默认值或者在样式文件指定的值,
specified value - 转换为可以被用来继承的值,
computed value - 转换为绝对值如果必要的时候,
used value - 根据实际环境转换为实际值,
actual value
specified value
首先 UA 必须为每一个属性赋予一个值,这个值:
- 如果在样式文件中指定了,那么使用它
- 否则,如果这个属性是可以继承的且不是根元素,那么使用父元素的 `computed
- 否则,使用这个属性的初始值(由规范指定)
可以认为这一步是先要获取一个默认值(因为每个属性必须有值)
computed value
由第一步得到的属性值,可能是绝对值也可能是相对值。
绝对值即不依赖其他值的值,例如 p{color: red,font-size: 14px;},这些值不需要计算转换,所以在第二步成为为 computed value
对于相对值,例如 width: 20%,必须要有一个参考值(依赖布局才能决定)才可以被计算出来。
还有一些相对值em,如 {font-size: 16px;padding-top: 2em},就直接转换为 {padding-top: 32px;},不需要等到第三步
used value
css 最终使用的值。computed value 是在不渲染文档最大程度处理的值。
但是有一些值只能在文档被确定布局之后才能决定。例如子元素的宽度设置为其包含块的 20% 等,那么子元素的宽度必须要等到包含块的宽度确定了才能确定。
所以 computed value 与 used value 的区别是:
- 前者是在页面展现之前,仅处理样式时就能得出的尽可能接近绝对的结果;
- 后者则是页面展示时,得出的绝对值。
actual value
原则上,used value 是可以被使用的,但是 UA 可能在一些环境中无法使用这个值,例如 UA 可能只允许渲染整数值的 border,这个时候就需要使用和 used value 接近的值。
这些有什么用?有一个例子是行高的继承,我们知道行高的设置有 数字、百分比、具体值,如果我们要设置一个页面所有内容都是行高为字体的2倍大小,比如:
哪个是正确的呢?答案是 line-height: 2,根据 规范:
<length>
The specified length is used in the calculation of the line box height. Negative values are illegal.<number>
The used value of the property is this number multiplied by the element’s font size. Negative values are illegal. The computed value is the same as the specified value.<percentage>
The computed value of the property is this percentage multiplied by the element’s computed font size. Negative values are illegal.
Refer
- CSS2.1 Selector REC - W3C
- CSS3 Selector REC - W3C
- cascade REC - W3C
- generate text - W3C
- Visual formatting model details - W3C
End.