样式计算-你CSS样式不生效的核心原因
遇到的问题
不知道各位在开发学习过程中有没有遇到自己明明给一个元素修改样式而不生效的情况呢。 例如我使用ant-design-vue组件库引入一个tab组件
<template>
<a-tabs v-model:activeKey="activeKey">
<a-tab-pane key="1" tab="Tab 1">Content of Tab Pane 1</a-tab-pane>
<a-tab-pane key="2" tab="Tab 2">Content of Tab Pane 2</a-tab-pane>
<a-tab-pane key="3" tab="Tab 3">Content of Tab Pane 3</a-tab-pane>
</a-tabs>
</template>
假设我现在不想让标签选择时为它默认的蓝色,而是想用红色该怎么办呢?
很容易可以想到的是我们修改它选中时的类样式就行了,
当我们打开调试面板,我们可以看到它是被选中时是给标签添加了一个类样式
ant-tabs-tab-active
,所以我们可以想到的是修改ant-tabs-tab-active
下的ant-tabs-tab-btn
样式就行了,
.ant-tabs-tab-active>.ant-tabs-tab-btn{
color:red;
}
但当我们在css中写入以下代码时样式却并没有生效。打开调试面板,我们会发现我们所写的样式被无情的划了一条删除线。
这是为什么呢?就让我们通过本篇文章来了解一下在编写css中到底是哪个样式在生效吧。
样式计算
什么是样式计算
首先我们要知道的是,任何一个html元素它都有一整套的css样式,我们在调试面板中 样式(styles) 部分看到的都是选中元素的一些浏览器的默认样式与我们开发者所编写的样式。而任何一个元素它所具有的样式不仅仅只有这些,并且还不一定全部生效,当我们查看调试面板中的 计算样式(computed) 部分时我们就可以看到一个元素在页面中产生效果的所有css属性,并且每一个属性都有值,同时在 计算样式(computed) 部分展示的样式才是页面元素真正呈现的样式,在js中我们通常会用getComputedStyle()
来获取这部分样式。
所以当我们知道这部分样式是如何计算而来的就对我们的css开发调试有着极其关键的作用。
样式计算过程
样式计算主要分为四个过程:1.确定声明值,2.解决层叠冲突,3.使用继承,4.使用默认值。 接下来就让我们来详细了解一下这四个过程。
确定声明值
声明值是指在css样式表中为每个属性设置的值,而样式表主要分为两类:
- 开发者样式表:就是我们开发者所编辑的样式表。
- 浏览器默认样式表:浏览器自带的样式表。
这两种样式表会同时作用于同一个选中���元素。而确定声明值就是在这两张样式表中找出没有冲突的属性值。
例如我写了一个p元素<p class="text">xump</p>
我们可以看到的是其初始有两个样式表,分别是开发者编写的
text
类样式,与用户代理样式表(也就是浏览器自带的样式表),而确定声明值会把样式表中所有的未冲突属性赋予对应值。在上例中就是完全没有冲突,也就是两个样式表全部生效。同时我们还有要注意的是在这个过程中会把所有相对单位转化为具体的数值,比如像em
、百分比之类的单位转化为具体多少px
。
解决层叠冲突
当多个相同属性样式作用于同一个元素时,被最终赋予元素的只会有一个,而层叠规则就决定哪个样式会具体应用到该元素。
按照层叠规则它会有三个部分的比较:
1. 比较重要性
这也是我们开发中最容易调试解决的,按重要性从高到低分别是:
- 带有
important
的开发者样式 - 带有
important
的浏览器默认样式 - 开发者样式
- 浏览器默认样式
2. 比较明确性
在vscode中编写css时,当我们将鼠标移到选择器名上我们就可以看到该样式选择器的明确性(也指特定性、特征性、特殊性等)了
在浏览器调试面板中将鼠标移到选择器名上也可看到
在上图中我们可以看到明确性由三位数组成:
- 第一位代表id选择器的数量
- 第二位表示属性、类、伪类的数量
- 第三位表示元素、伪元素的数量
就像这个例子它有两个id选择器(#title
与#name
),所以第一位为2;有两个类选择器(.text
与.name-text
)和一个属性([isShow = "true"]
),所以第二位为3;有两个元素(分别为p
和p
的::after
伪元素)所以第三位为2,综合起来这个样式的明确性为(2,3,2)
。
其实这个明确性还有第0位,表示该样式是否为内联样式,如果是内联样式则为1,否则为0;
在这个过程中它会根据选择性的明确性依次从第0位开始比较,明确性较高的样式选择器就会优先生效。
3. 比较源次序
就是在css的源码中靠后的会覆盖靠前的,但前提是前两次比较还没有结果。
使用继承
在样式计算过程中,因为要让一个元素的所有属性都有值,所以对于哪些经过前两步骤还没有值得属性,如果可以继承(并非所有属性都可以继承)则会使用继承。
使用默认值
当通过上三步骤还没有值的话,它就会为每一个还没有值的属性赋予默认值,在MDN上针对每一个css属性都会有一个默认值,最后使每一个元素的css中的每一个属性都有值。
问题的解决
在我们了解属性的计算过程后回归到开始遇到的问题,不知道各位有没有解决问题的思路了呢,我就来按属性计算的各过程来相继解决解决吧。
问题的定位与方案
首先我们要知道这是属于什么问题,显而易见的是样式冲突问题,那么我就可以通过如何层叠冲突的过程入手啦。
从重要性
在重要性中带有important
的开发者样式排在第一位,所以我们直接在color
后面加上!important
问题很轻易就解决了(虽然这样可以解决问题,但是我们在开发过程中要尽量的少用important
,因为这会导致代码冗余、难以维护、破坏层叠等问题)。
.ant-tabs-tab-active>.ant-tabs-tab-btn{
color:red !important;
}
从明确性
在修改明确性前我们首先要知道的是它原来样式的明确性为多少。我们在调试面板中可查看到其明确性为(0,4,0)
因为有四个类选择器。
所以我们将代码修改为如下时,
.ant-tabs .ant-tabs-tab.ant-tabs-tab-active>.ant-tabs-tab-btn[aria-selected="true"]{
color:red;
}
将修改后的明确性提升至(0,5,0)
(四个类选择器和一个属性)问题也得到了解决。
从源次序
比较源次序的前提是前两者相同,所以我们所写的样式也应明确性(0,4,0)
,并且在默认情况下组件库的样式表就是在我们所编写代码的前面(即我们写的样式属于靠后)。故我们的代码会覆盖掉组件库中的样式。
转载自:https://juejin.cn/post/7392399628199854115