前端 css selector 的层叠 优先级与继承
文章目录
- 1. 层叠
- 2. 优先级
- 3. 继承
- 4. 以上三种协同工作的方式.
- 4.1 控制继承
- 4.2 重设所有属性
- 4.3 层叠
- 4.3.1 资源顺序
- 4.3.2 优先级
- 4.3.3 内联样式
- 4.4 级联层的顺序
1. 层叠
当应用两条同级别的规则到一个元素的时候,写在后面的就是实际使用的规则。
举例说明:
<h1>这是一个h1标题。</h1>
h1 {color: red;
}
h1 {color: blue;
}
渲染效果如下:

由于css中的两个h1是同一个选择器, 优先级相同, 所以按前后顺序,后面的覆盖前端的,所以生效的是 blue.
2. 优先级
当多个规则有不同选择器对应相同的元素的时候, 浏览器是根据优先级来决定需要使用哪个规则。它基本上是一个衡量选择器具体选择哪些区域的尺度:
- 一个元素选择器不是很具体,则会选择页面上该类型的所有元素,所以它的优先级就会低一些。
- 一个类选择器稍微具体点,则会选择该页面中有特定 class 属性值的元素,所以它的优先级就要高一点。
越具体,优先级越高
示例如下:
<h1 class="main-heading">这是我的标题。</h1>
.main-heading {color: red;
}h1 {color: blue;
}
渲染如下:

3. 继承
一些设置在父元素上的 CSS 属性是可以被子元素继承的,有些则不能。
举一个例子,如果你设置一个元素的 color 和 font-family,每个在里面的元素也都会有相同的属性,除非你直接在元素上设置属性。
示例:
<body><p>由于主题颜色被设置为蓝色,因此该颜色会被子元素继承。</p><p>我们可以通过选择器定位元素来改变颜色,比如这个<span>内容跨越</span>元素。</p>
</body>
body {color: blue
}span {color: red;
}
渲染如下:

不能被继承的属性有: width、margin、padding 和 border
示例:
<body><ul class="main"><li>项目 1</li><li>项目 2<ul><li>2.1</li><li>2.2</li></ul></li><li>项目 3<ul class="special"><li>3.1<ul><li>3.1.1</li><li>3.1.2</li></ul></li><li>3.2</li></ul></li></ul>
</body>
.main {color: rebeccapurple;border: 2px solid black;padding: 1em;
}.special {color: black;font-weight: bold;
}
渲染如下:

4. 以上三种协同工作的方式.
4.1 控制继承
CSS 为控制继承提供了五个特殊的通用属性值。每个 CSS 属性都接收这些值。
-
inherit(继承)
设置该属性会使子元素属性和父元素相同。实际上,就是“开启继承”。 -
initial(初始值)
将应用于选定元素的属性值设置为该属性的初始值。 -
revert(还原 )
将应用于选定元素的属性值重置为浏览器的默认样式,而不是应用于该属性的默认值。在许多情况下,此值的作用类似于 unset。 -
revert-layer(还原到上一次)
将应用于选定元素的属性值重置为在上一个层叠层中建立的值。 -
unset(未设置)
将属性重置为自然值,也就是如果属性是自然继承那么就是 inherit,否则和 initial 一样。
<body><ul><li>默认<a href="#">链接</a>颜色</li><li class="my-class-1">继承<a href="#">链接</a>颜色</li><li class="my-class-2">重置<a href="#">链接</a>颜色</li><li class="my-class-3">取消<a href="#">链接</a>颜色的设置</li></ul>
</body>
body {color: green;/* body颜色 */
}.my-class-1 a {color: inherit;/* 继承body颜色 */
}.my-class-2 a {color: initial;/*重置 使用初始化颜色 */
}.my-class-3 a {color: unset;/* 不定义颜色,所以使用了父级颜色 */
}
渲染如下:

4.2 重设所有属性
关键字: all, 可以用于同时将这些继承值中的一个应用于(几乎)所有属性。它的值可以是其中任意一个(inherit、initial、unset 或 revert)。这是一种撤销对样式所做更改的简便方法,以便回到之前已知的起点。
<body><blockquote><p>当前块引用设置了样式</p></blockquote><blockquote class="fix-this"><p>当前块引用未设置样式</p></blockquote>
</body>
blockquote {background-color: orange;border: 2px solid blue;
}.fix-this {all: unset;
}
渲染如下:

4.3 层叠
有三个因素需要考虑,根据重要性排序如下(序号数字越大越重要):
- 资源顺序
- 优先级
- 重要程度
4.3.1 资源顺序
这个很简单, 仅在规则的优先级相同时才体现出来,后面的覆盖前面的。
4.3.2 优先级
- 选择器的影响范围越具体,优先级越高。即类选择器的权重高于元素选择器的权重。
- 不同优先级的选择器中, 相同的属性会被覆盖,
<body><h2>未设置类的标题</h2><h2 class="small">设置了 small 类的标题</h2><h2 class="bright">设置了 bright 类的标题</h2>
</body>
h2 {font-size: 2em;color: #000;font-family: Georgia, "Times New Roman", Times, serif;
}
/* 类选择器的优先级高于元素选择器, 所以优先使用类选择器中的属性,但只覆盖同名属性。 */
.small {font-size: 1em; /* 仅覆盖了h2中的同名属性 */
}.bright {color: rebeccapurple; /* 仅覆盖了h2中的同名属性 */
}

- 选择器的优先级计算逻辑:
不同类型的选择器有不同的分数值,把这些分数相加就得到特定选择器的权重,然后就可以进行匹配了。
一个选择器的优先级可以说是由三个不同的值相加, 可以认为是百(ID)位,十(类)位, 个(元素)位——三位数的三个位数: - ID:选择器中包含 ID 选择器则百位得一分。
- 类:选择器中包含类选择器、属性选择器或者伪类则十位得一分。
- 元素:选择器中包含元素、伪元素选择器则个位得一分。
示例如下:
| 选择器 | ID | 类 | 元素 | 优先级 |
|---|---|---|---|---|
| h1 | 0 | 0 | 1 | 0-0-1 |
| h1 + p::first-letter | 0 | 0 | 3 | 0-0-3 |
| li > a[href*=“en-US”] > .inline-warning | 0 | 2 | 2 | 0-2-2 |
| #identifier | 1 | 0 | 0 | 1-0-0 |
| button:not(#mainBtn, .cta) | 1 | 0 | 1 | 1-0-1 |
<body><div class="container" id="outer"><div class="container" id="inner"><ul><li class="nav"><a href="#">一</a></li><li class="nav"><a href="#">二</a></li></ul></div></div>
</body>
/* 1. 优先级:1-0-1 */
#outer a {background-color: red;
}/* 2. 优先级:2-0-1 */
#outer #inner a {background-color: blue;
}/* 3. 优先级:1-0-4 */
#outer div ul li a {color: yellow;
}/* 4. 优先级:1-1-3 */
#outer div ul .nav a {color: white;
}/* 5. 优先级:0-2-4 */
div div li:nth-child(2) a:hover {border: 10px solid black;
}/* 6. 优先级:0-2-3 */
div li:nth-child(2) a:hover {border: 10px dashed black;
}/* 7. 优先级:0-3-3 */
div div .nav:nth-child(2) a:hover {border: 10px double black;
}a {display: inline-block;line-height: 40px;font-size: 20px;text-decoration: none;text-align: center;width: 200px;margin-bottom: 10px;
}ul {padding: 0;
}li {list-style-type: none;
}
渲染如下:

4.3.3 内联样式
内联样式,即 style 属性内的样式声明,优先于所有普通的样式,无论其优先级如何。这样的声明没有选择器,但它们的优先级可以理解为 1-0-0-0;即无论选择器中有多少个 ID,它总是比其他任何优先级的权重都要高。
它就是!important, 这是一个特殊的 CSS, 可以用来覆盖所有上面所有优先级计算,不过需要很小心的使用。
它用于修改特定属性的值,能够覆盖普通规则的层叠。
<p class="better">这是个段落。</p>
<p class="better" id="winning">一个选择器掌管一切!</p>
#winning {background-color: red;border: 1px solid black;
}.better {background-color: gray;border: none !important;
}p {background-color: blue;color: white;padding: 5px;
}
渲染如下:

覆盖 !important 唯一的办法就是另一个 !important 具有相同优先级而且顺序靠后,或者更高优先级。
4.4 级联层的顺序
当你在不同的层中有多个样式块,且其中提供了对于某一元素的单一属性的相互冲突的值时,声明该冲突样式的层的顺序将决定其优先级。而不是高优先级的层直接覆盖低优先级的层中的所有样式。需要注意的是单独的一个层中的样式的优先级仍旧会起作用。
示例如下:
<body><p id="addSpecificity">具有边框和背景的段落</p>
</body>
@layer firstLayer, secondLayer;p {/* 0-0-1 */background-color: red;color: grey !important;border: 5px inset purple;
}p#addSpecificity {/* 1-0-1 */border-style: solid !important;
}@layer firstLayer {#addSpecificity {/* 1-0-0 */background-color: blue;color: white !important;border-width: 5px;border-style: dashed !important;}
}@layer secondLayer {p#addSpecificity {/* 1-0-1 */background-color: green;color: orange !important;border-width: 10px;border-style: dotted !important;}
}
渲染结果如下:

示例中,声明了两个级联层,按 firstLayer 和 secondLayer 的顺序声明。即使 secondLayer 的优先级更高,但其中声明的样式没有被使用。为什么?
因为不论层的优先级如何,不分层的常规样式具有更高的优先级,覆盖了层中的常规样式;
而具有级联层的样式,则是先前声明的层会覆盖后声明的层,而不是层的优先级。
