0x1:层叠、优先级和继承 【CSS in Depth】

废话不多说,正式开读。

层叠

CSS本质上就是声明规则,即在各种条件下,我们希望产生特定的效果。

当元素有这个类时,我们使用其中一个规则;当有多个类时,如何选择使用哪个规则?

层叠指的就是这一系列规则。它决定了如何解决冲突,是CSS语言的基础。

当声明冲突时,层叠会依据三种条件解决冲突:

  1. 样式表来源
  2. 选择器优先级
  3. 源码出现的顺序

1. 样式表来源

  • 作者样式表:即你写的样式表
  • 用户代理样式表:浏览器默认样式

其中作者样式表的优先级会高于用户代理样式表,因此你写的样式会覆盖掉默认样式。

在此之外,还有一个特别的 !important 声明。标记了!important的声明会被当作更高优先级的来源,因此它会高于作者样式表中其它规则。

2. 优先级

如果无法用来源解决冲突声明,浏览器会尝试检查它们的优先级。

通常浏览器会将优先级分为两部分:

  • 行内样式
  • 选择器优先级

行内样式

行内样式,就是在HTML内直接写的样式。

<p style="color:red">大鹅真帅</p>

行内样式只会作用于当前的元素。实际上行内元素属于“带作用域的”声明,它会覆盖任何来自样式表或者标签的样式。

为了在样式表里覆盖行内声明,需要为声明添加!important,这样能将它提升到一个更高优先级的来源。但如果行内样式也被标记为!important,就无法覆盖它了。最好是只在样式表内用!important。

选择器优先级

优先级的第二部分由选择器决定。

比如,有两个类名的选择器比只有一个类名的选择器优先级更高。但是选择器的长度并不是决定优先级的唯一因素。

不同类型的选择器有不同的优先级。比如,ID选择器比类选择器优先级更高。实际上,ID选择器的优先级比拥有任意多个类的选择器都高。

伪类选择器(如:hover)和属性选择器(如[type=“input”]​)与一个类选择器的优先级相同。通用选择器(*)和组合器(>、+、~)对优先级没有影响。

通常最好让优先级尽可能低,这样当需要覆盖一些样式时,才能有选择空间。

关于选择器的优先级,请参考我之前的帖子 【基础巩固】CSS选择器的优先级与权重计算,全程干货! ,里面有更详细的介绍,内容过多,这里不多赘述。

3. 源码顺序

如果两个声明的来源和优先级相同,其中一个声明在样式表中出现较晚,或者位于页面较晚引入的样式表中,则该声明胜出。

优先级相同时,后出现的样式会覆盖先出现的样式。如果一个元素同时处于两个或者更多状态,最后一个状态就能覆盖其他状态。

浏览器遵循三个步骤,即来源、优先级、源码顺序,来解析网页上每个元素的每个属性。

继承

1. 可继承属性

默认情况下,只有特定的一些属性能被继承,主要是跟文本相关的属性。

color line-height letter-spacing word-spacing
font-family font-size font-weight font-variant
text-align text-indent text-transform white-space

有一些其他的属性也可以被继承

list-stylelist-style-typelist-style-positionlist-style-imageborder-collapseborder-spacing

我们可以使用开发者工具看到应用了哪些样式规则、哪些属于继承

样式检查器显示了所检查元素的每个选择器,它们根据优先级排列。在选择器下方是继承属性。元素所有的层叠和继承一目了然。

2. 特殊值

有两个特殊值可以赋给任意属性,用于控制层叠:inheritinitial

inherit 关键字

有时,我们想用继承代替一个层叠值。这时候可以用inherit关键字。可以用它来覆盖另一个值,这样该元素就会继承其父元素的值。

例如:一个footer组件,我们需要里面的a链接颜色继承父元素的,而不是显示默认蓝色。

<footer>
  <a href="xxx">
</footer>

<style>
  footer{color:gray}
  footer a {color:inherit}
</style>

这样做的好处是,当父元素颜色变化时,可以根据父元素的颜色自动变化,而不是固定一个颜色,更加灵活。

还可以使用inherit关键字强制继承一个通常不会被继承的属性,比如边框和内边距。

initial 关键字

有时,你需要撤销作用于某个元素的样式。这可以用initial关键字来实现。

每一个CSS属性都有初始(默认)值。如果将initial值赋给某个属性,那么就会有效地将其重置为默认值,这种操作相当于硬复位了该值。

例如:如果想删除一个元素的边框,设置border: initial即可。如果想让一个元素恢复到默认宽度,设置width: initial即可。

通常我们都会使用 width: auto 来重置,这与 width: initial是相同的,因为width的默认值就是auto。但是需要注意:auto不是所有属性的默认值,对很多属性来说甚至不是合法的值。

声明display: initial等价于display: inline。不管应用于哪种类型的元素,它都不会等于display: block。这是因为 initial重置为属性的初始值,而不是元素的初始值。 inline才是display属性的初始值。

3. 简写

简写属性

我们常用的一些属性其实都是简写,例如font、background、border等,以font为例,它是font-style、font-weight、font-size、font-height以及font-family的简写。

font:italic bold 18px/1.2 "jetbrains mono",sans-serif;

大多数简写属性可以省略一些值,只指定我们关注的值。但是要知道,这样做仍然会设置省略的值,即它们会被隐式地设置为初始值。这会默默覆盖在其他地方定义的样式。

在简写属性中,font会有太多的问题,因此不建议在开发中使用font简写。

简写值的顺序

简写属性会尽量包容指定的属性值的顺序。例如 border: 1px solid blackborder: black 1px solid 的效果是相同的。这是因为浏览器知道宽度、颜色、边框样式分别对应什么类型的值。

但是有很多属性的值很模糊。例如 marginpadding等。它们的值甚至也可以简写为一个值、两个值、三个值等。

默认顺序为:上、右、下、左。声明结束还未指定的值,会取其对边的值。

取对边的值是什么意思呢?假设我们设置了三个值,那就是 没有设置,那它就取 的值,相当于第二个值同时代表了左和右。

以此类推,简单记忆如下:

  • 单值:四边相同
  • 两值:上下、左右
  • 三值:上、左右、下

先水平还是先垂直

我们上述的例子都是给元素设置四条边的值,对于一些属性来说,它们只有两个值,例如 background-position。它们的顺序与我们上述却是相反的!

padding: 1em em;

根据规则,我们知道设置了上下、左右的内边距,也就是先是垂直方向,然后是水平方向。

background-position: 25% 75%;

然而, background-position 却是水平方向在前,然后才是垂直方向的。

这是因为,两个值的属性是使用了笛卡尔坐标系,因此其值也是按照笛卡尔网格坐标(x,y)来的。

如果属性需要指定从一个点出发的两个方向的值,就先水平再垂直​。
如果属性需要指定一个元素四个方向的值,就先垂直再水平​。

鹅曰

作为开篇,本章内容较为基础,也都是一些理论上的东西,但这些基础,对我们后面的影响可以说是翻天覆地。基础不牢,地动山摇啊!后续的内容会慢慢复杂,也会配合实际案例去解读和理解,慢慢来吧!


你可以在这里找到大鹅所有CSS知识分享哦
:red_triangle_pointed_down::red_triangle_pointed_down::red_triangle_pointed_down::red_triangle_pointed_down::red_triangle_pointed_down:
🔥【冷门知识】鹅のCSS大合集!长期追更~ 收藏 ≈ 学会

30 个赞

哇!大鹅又更新了!

3 个赞

大帅哥也太快了!

4 个赞

跟大鹅佬学习

3 个赞

大鹅太强了!

3 个赞

学起来。。

3 个赞

这是第一堂课,收藏了

3 个赞

感谢分享啦

3 个赞

居然在摸鱼的时候学习!

3 个赞

感谢大佬,开始上学

3 个赞

和大鹅一起学习!

3 个赞

哇,老师我忘带教材了

3 个赞

鹅子曰:基础不牢,地动山摇啊!

大鹅老师太强了! :partying_face:

3 个赞

我火速加入书签! :tieba_087:

3 个赞

我学会了 :lark_085:

2 个赞

鹅佬又开课啦

2 个赞

感谢领读,咱也是时候该补补 CSS 基础了。感觉咱写 CSS 经常在靠感觉来拼积木,尤其是优先级这一块 :joy:

2 个赞

全文默写!

4 个赞

我也学会了 :tieba_002:

2 个赞

哈哈,不过确实就是拼积木 :tieba_087:

3 个赞