开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第2天,点击查看活动详情
今天开始“重学CSS”计划,其实是想通过「回顾 CSS 核心知识,阅读经典书籍和技术专栏,做一些有趣的练习」这样的路线进入“玩起CSS”的状态。大概对我来说,前端有趣的点之一是能实现设计,让优雅的视觉交互成真。每天学一点,在掘金输出成果。
今天阅读的是《深入解析CSS》的第一章“层叠、优先级和继承”,层叠和继承虽然简单,却是 CSS 的灵魂,作为 CSS 中的 C(cascade)层叠的作用不容小觑。
为什么需要层叠?
CSS 本质上是声明一系列规则,一条规则 = 选择器 + 声明块,一条声明 = 属性 + 值
于是有一个问题,当两条规则提供的声明冲突时哪一个会生效呢?我们需要一些规则来维护秩序,这些规则称为“层叠规则”。
层叠规则
层叠就是比较三个因素,决出优先级更高的声明。三个因素是
- 样式来源
- 选择器的优先级
- 源码顺序
判断流程如图所示
层叠规则的应用:超链接伪类的书写顺序
a:link {
color: #0269c8;
}
a:visited {
color: #1f4bc2;
}
a:hover {
color: #275b8c;
}
a:active {
color: #091c2e
}
超链接存在 :link(有链接),:visited(已访问),:hover(悬停),:active(点击) 四个状态。
四个状态有可能叠加存在,比如点击时既是 active 又是hover,如果href有值还满足link,但点击时需要 active 状态优先。按照交互逻辑,需要写出优先级 active > hover > visited > link 的效果。
四种选择器的优先级一样,所以通过源码顺序来调整。
经验法则:尽量使用低优先级写法。
优先级容易发展成一种“军备竞赛”。在大型项目中这一点尤为突出,通常最好让优先级尽可能低,这样当需要覆盖一些样式时,才能有选择空间。
克制地挑选选择器结构,为后续维护留有余地。这也是尽量避免使用 !important 和 ID 选择器的原因,尽量使用样式表选择器而非行内样式也有这方面的考量。
继承
通过层叠规则判断出优先声明后,一个元素属性的层叠值也计算出来了。
如果所有样式表中都没有声明一个元素的某个属性,接着可能会去继承某个祖先元素的值。
并不是所有属性都是能被继承的,这和属性的规范定义相关。
与继承有关的关键字是inherit,去强制继承父元素的值。神奇的是一些规范定义中不会被继承的属性,也可以用 inherit 实现强制继承。
默认值
那些无法被继承的属性将使用默认值,属性的默认值同样是由规范定义的。
和默认值相关的关键字是initial,用来恢复属性的默认值。有一个有趣的知识点,display 属性的默认值是 inline,并不会根据元素的类型变化。
Tips
1.在 DevTool Elements Styles 面板中查看层叠和继承情况
2.简写中忽略的属性将会隐式使用默认值
例如写 font: 12px red,font-weight/font-style/line-height 等属性会被隐式设置回默认值
3.简写方向写法妙记
需要指定四个方向的值,就想想时钟“上右下左”,例如 margin/padding。需要指定两个方向的值,就想想笛卡尔网络要按照x/y的顺序来指定坐标,例如 box-shadow/text-shadow/background-position
总结
CSS 的本质是声明一系列规则,当多个规则中的声明冲突时,通过层叠来决出优胜声明,计算出元素属性的层叠值。
如果属性没有层叠值,可继承的属性会取父元素或祖先元素的值,不可继承的属性会使用默认值。
层叠的判断方法是:先比较样式来源,如果一致再比较选择器的优先级,最后比较源码顺序。