一篇文章带你初步了解—CSS特指度
CSS特指度
说明
这篇博客在在两台电脑上分别完成的,故而有些截图是Firefox,有些是Chrome,有些改动了浏览器的用户样式表,有些没改,但不会影响阅读,特此说明,勿怪。
CSS选择器
单个CSS选择器
css选择器决定css样式能渲染到对应的元素上。
元素选择器:

Class选择器:

ID选择器:

多个CSS选择器
浏览器在处理单独的id、class和元素选择器时如何渲染的问题很好理解,但要在两种甚至三种不同选择器同时作用于相同的元素的情况下,浏览器又该如何渲染呢?
比如3个选择器作用在同一个元素身上的例子:
<!DOCTYPE html>
<html>
<head>
<meta name="charset" content="utf-8"/>
<title>ICE计算公式</title>
<style type="text/css">
#title {
color : blue;
}
.red {
color : red;
}
p {
color : brown;
}
</style>
</head>
<body>
<p id="title" class="red">这是标题</p>
</body>
</html>
得出结果:

当3个不同的选择器(ID、Class、元素)同时作用于同一元素上时,浏览器渲染时选择的样式为ID选择器声明的样式,这是因为ID选择器的特指度高于Class选择器,而Class选择器的特指度高于元素选择器......
那么应该怎么计算每个选择器特指度,要解决这个问题,不得不提到ICE计算公式:ID-Class-Element。
ICE计算公式
关于ICE计算公式错误的理解
注:我在过去很长一段时间都是按照这种错误的思想来理解ICE计算公式的,务必注意。
关于ICE计算公式,经常看到这样的说法(这是错误的):
| !important | ID | Class | Element | |
|---|---|---|---|---|
| 特指度 | 1000 | 100 | 10 | 1 |
Element特指度为1,class特指度为10,ID特指度为100,!important为1000。
如果按照这样理解,是不是可以说11个class的特指度为10 * 11 === 110,它是肯定比1个Id的特指度要大的,但在我实践后,我发现不能这样去理解,就比如下面的例子:
<!DOCTYPE html>
<html>
<head>
<meta name="charset" content="utf-8"/>
<title>11个class是否比1个ID特指度大</title>
<style type="text/css">
#id {
color : green;
}
.class1.class2.class3.class4.class5.class6.class7.class8.class9.class10.class11 {
color: red;
}
</style>
</head>
<body>
<p id="id" class="class1 class2 class3 class4 class5 class6 class7 class8 class9 class10 class11">p标签</p>
</body>
</html>
如果按照class特指度为10、id为100的逻辑来理解,110 大于 100,最后p标签的color属性值应该为red,但是实际情况却是:

标签的color属性值为green。造成这样结果的原因是因为不管有多少个class选择器,Id选择器的特指度就是比class选择器的特指度大。就好比奥运会排名,先比较金牌,金牌数量多者排前面,数量少者排后面,在出现金牌数量相同时才会以银牌的数量来比较。Id选择器就好比金牌,而class选择器就好比银牌。当Id选择器数量不一致时,后续操作压根就不会去比较class选择器,所以class选择器的数量再多,也是无效的。
不同选择器对应的特指度
选择器共有:
- ID选择器
- Class选择器
- 元素选择器
- 属性选择器
- 伪类选择器
- 伪元素选择器
ID选择器
\(\color{#FF3030}{Selector Specificity: (1, 0, 0)}\)
#title {
color : blue;
}
Class选择器
\(\color{#FF3030}{Selector Specificity: (0, 1, 0)}\)
.red {
color : red;
}
元素选择器
\(\color{#FF3030}{Selector Specificity: (0, 0, 1)}\)
p {
color : brown;
}
属性选择器
\(\color{#FF3030}{Selector Specificity: (0, 1, 0)}\)
[id="title"] {
color : black;
}
伪类选择器
\(\color{#FF3030}{Selector Specificity: (0, 1, 0)}\)
注意:p:hover的特指度为 (0, 1, 1),因为它包含了元素选择器和伪类选择器
p:hover {
color: #FF00FF
}
伪元素选择器
\(\color{#FF3030}{Selector Specificity: (0, 0, 1)}\)
注意:p::after的特指度为 (0, 0, 2),因为它包含了元素选择器和伪元素选择器
p::after {
content: "元";
}
代码:
<!DOCTYPE html>
<html>
<head>
<meta name="charset" content="utf-8"/>
<title>6种选择器的特指度</title>
<style type="text/css">
#title {
color : blue;
}
.red {
color : red;
}
p {
color : brown;
}
[id="title"] {
color : black;
}
p:hover {
color: yellow;
}
p::after {
content: "元";
}
</style>
</head>
<body>
<p id="title" class="red">100</p>
</body>
</html>
其余还有组合选择器、分组选择器、上下文选择器、子元素选择器、相邻兄弟选择器、后续兄弟选择器,但是这几种更像是选择器的组合,它们也都是由上述6种选择器 \(\color{#FF3030}{(ID选择器、Class选择器、元素选择器、属性选择器、伪类选择器、伪元素选择器)}\)组合而成,所以它们的特指度由组成它们的选择器的特指度相加即可获得。
比如:
组合选择符
\(\color{#FF3030}{Selector Specificity: (0, 2, 0)}\)
注意:此处是对Class属性中同时含有red和indigo两个值的元素进行声明,它的特指度为(0, 2, 0)
.red.indigo {
color : brown;
}
分组选择符
\(\color{#FF3030}{Selector Specificity: (0, 0, 1)}\)
注意:此处是对p、em、strong3个元素分别进行声明,而它们3个的特指度都为(0, 0, 1)
p , em , strong {
color : red;
}
上下文选择符
\(\color{#FF3030}{Selector Specificity: (0, 0, 2)}\)
注意:此处是对被包含在p元素中的em元素(\(\color{#FF3030}{此时的em元素可以为p元素的子孙元素}\))进行声明,它的特指度为(0, 0, 2)
p em {
color : red;
}
子元素选择符
\(\color{#FF3030}{Selector Specificity: (0, 0, 2)}\)
注意:此处是对被包含在p元素中的em元素(\(\color{#FF3030}{此时的em元素只能为p元素的子元素}\))进行声明,它的特指度为(0, 0, 2)
p > em {
color : green;
}
相邻兄弟选择符
\(\color{#FF3030}{Selector Specificity: (0, 0, 2)}\)
注意:此处是对与p元素拥有相同父元素的em元素(\(\color{#FF3030}{此时的em元素必须紧跟在p元素的后面}\))进行声明,它的特指度为(0, 0, 2)
p + em {
color : red;
}
一般兄弟选择符
\(\color{#FF3030}{Selector Specificity: (0, 0, 2)}\)
注意:此处是对与p元素拥有相同父元素的em元素(\(\color{#FF3030}{此时的em元素必须在p元素的后面,但不一定紧跟}\))进行声明,它的特指度为(0, 0, 2)
p ~ em {
color : red;
}
特殊情况
没有特指度的继承样式
继承样式不考虑特指度,由下面两个例子能说明:
<!DOCTYPE html>
<html>
<head>
<meta name="charset" content="utf-8"/>
<title>继承样式不考虑特指度</title>
<style type="text/css">
.yellow {
color : yellow;
}
</style>
</head>
<body>
<div class="yellow">
<p>p标签</p>
</div>
</body>
</html>

上述例子中p元素的color属性值为red(来自用户样式表),继承自div元素的color属性值yellow被覆盖。
(\(\color{#FF3030}{注:此浏览器的用户样式表被我修改,没有修改过的p元素的color属性的值应该是black。}\))
<!DOCTYPE html>
<html>
<head>
<meta name="charset" content="utf-8"/>
<title>继承样式不考虑特指度</title>
<style type="text/css">
.yellow {
color : yellow;
}
p {
color : green;
}
</style>
</head>
<body>
<div class="yellow">
<p>p标签</p>
</div>
</body>
</html>

上述例子中p元素的color属性值为green(来自元素选择器),继承自div元素的color属性值yellow被覆盖。
超脱特指度的 !important
!important是超脱特指度的存在
<!DOCTYPE html>
<html>
<head>
<meta name="charset" content="utf-8"/>
<title>!important是超脱特指度的存在</title>
<style type="text/css">
#id {
color : green;
}
p {
color : brown;
}
</style>
</head>
<body>
<p id="id">p标签</p>
</body>
</html>

修改代码,给元素选择器中color属性加上!important后:
<!DOCTYPE html>
<html>
<head>
<meta name="charset" content="utf-8"/>
<title>!important是超脱特指度的存在/title>
<style type="text/css">
#id {
color : green;
}
p {
color : brown !important;
}
</style>
</head>
<body>
<p id="id">p标签</p>
</body>
</html>

元素选择器中加了!important的声明覆盖了ID选择器中没加!important的声明。
特指度相当时 以 后声明的属性为准
当两个选择器的特指度相当时,特指度相当时 以 后声明的属性为准。
<!DOCTYPE html>
<html>
<head>
<meta name="charset" content="utf-8"/>
<title>特指度相当时 以 后声明的属性为准</title>
<style type="text/css">
p {
color : green;
}
p {
color : brown;
}
</style>
</head>
<body>
<p>p标签</p>
</body>
</html>

后声明的属性覆盖了先声明的属性。
总结
单个选择器的特指度按照 !important > id选择符 > class选择符、属性选择符和伪类 > 元素选择符和伪元素的规律排序,如果遇到组合选择器,则按其逻辑将其拆分为单个选择器后相加再进行判断。如果选择器中的声明包含了!important,则这条属性会覆盖同属性所有不包含了!important的声明,只有在同属性的声明也包含!important,并且同属性的声明位于的选择器的特指度大于先前的选择器,亦或两个选择器的特指度相当,但同属性的声明位于的选择器位于先前的选择器之后时,才会覆盖先前的选择器的加了!important的属性。
如果上面的话很难理解,可以看这里的:
第一条:比较各自所在的选择器的特指度,特指度越大的优先级越高;
第二条:加了!important的声明的属性优先级最高,在都加了!important的情况下按第一条为准;
第三条:在特指度相等的情况下,后声明的优先级大于先声明的;
第四条:优先级高的样式覆盖优先级低的样式。
一篇文章带你初步了解—CSS特指度的更多相关文章
- 一篇文章带你了解网页框架——Vue简单入门
一篇文章带你了解网页框架--Vue简单入门 这篇文章将会介绍我们前端入门级别的框架--Vue的简单使用 如果你以后想从事后端程序员,又想要稍微了解前端框架知识,那么这篇文章或许可以给你带来帮助 温馨提 ...
- 一篇文章带你了解轻量级Web服务器——Nginx简单入门
一篇文章带你了解轻量级Web服务器--Nginx简单入门 Nginx是一款轻量级的Web服务器/反向代理服务器及电子邮件代理服务器 在本篇中我们会简单介绍Nginx的特点,安装,相关指令使用以及配置信 ...
- MYSQL(基本篇)——一篇文章带你走进MYSQL的奇妙世界
MYSQL(基本篇)--一篇文章带你走进MYSQL的奇妙世界 MYSQL算是我们程序员必不可少的一份求职工具了 无论在什么岗位,我们都可以看到应聘要求上所书写的"精通MYSQL等数据库及优化 ...
- MYSQL(进阶篇)——一篇文章带你深入掌握MYSQL
MYSQL(进阶篇)--一篇文章带你深入掌握MYSQL 我们在上篇文章中已经学习了MYSQL的基本语法和概念 在这篇文章中我们将讲解底层结构和一些新的语法帮助你更好的运用MYSQL 温馨提醒:该文章大 ...
- 一篇文章带你掌握主流数据库框架——MyBatis
一篇文章带你掌握主流数据库框架--MyBatis MyBatis 是一款优秀的持久层框架,它支持自定义 SQL.存储过程以及高级映射. 在之前的文章中我们学习了MYSQL和JDBC,但是这些东西远远不 ...
- 一篇文章带你掌握主流基础框架——Spring
一篇文章带你掌握主流基础框架--Spring 这篇文章中我们将会介绍Spring的框架以及本体内容,包括核心容器,注解开发,AOP以及事务等内容 那么简单说明一下Spring的必要性: Spring技 ...
- 一篇文章带你掌握主流服务层框架——SpringMVC
一篇文章带你掌握主流服务层框架--SpringMVC 在之前的文章中我们已经学习了Spring的基本内容,SpringMVC隶属于Spring的一部分内容 但由于SpringMVC完全针对于服务层使用 ...
- 一篇文章带你掌握主流办公框架——SpringBoot
一篇文章带你掌握主流办公框架--SpringBoot 在之前的文章中我们已经学习了SSM的全部内容以及相关整合 SSM是Spring的产品,主要用来简化开发,但我们现在所介绍的这款框架--Spring ...
- 一篇文章带你掌握MyBatis简化框架——MyBatisPlus
一篇文章带你掌握MyBatis简化框架--MyBatisPlus 我们在前面的文章中已经学习了目前开发所需的主流框架 类似于我们所学习的SpringBoot框架用于简化Spring开发,我们的国人大大 ...
随机推荐
- 带你探究Python的诞生和由来
最近,Python语言越来越火,那什么是Python?它怎么诞生的?它跟C语言.shell语言有什么区别?语言环境是怎么样的?下面,跟着我的步伐,一起去了解一下吧~ Python 诞生在一个圣诞节 P ...
- C# 多态virtual标记重写 以及EF6 查询性能AsNoTracking
首先你如果不用baivirtual重写的话,系统默认会为du你加new关键字,他zhi的作用是覆盖,而virtual的关键作用在dao于实现多态 virtual 代表在继承了这个类的子类里面可以使用o ...
- Blogs实现侧边公告栏设置
说明:只需要在博客侧边栏公告(支持HTML代码) (支持 JS 代码)里面添加如下代码 #1.博客运行时长统计 <!--博客运行时长显示开始--!> <div id="sh ...
- Error:(12, 24) 警告: [deprecation] android.hardware中的Camera已过时.android
问题:android studio编译项目时出现: Error:(12, 24) 警告: [deprecation] android.hardware中的Camera已过时 解决:(只是让其不提示) ...
- String 和 StringBuffer,StringBuilder 的区别
String 和 StringBuffer,StringBuilder 的区别 String 是 " 字符串常量" , 对象一旦创建就不可改变,这就导致如果字符串常量池中没有所需对 ...
- 小白经典CNN论文复现系列(一):LeNet1989
小白的经典CNN复现系列(一):LeNet-1989 之前的浙大AI作业的那个系列,因为后面的NLP的东西我最近大概是不会接触到,所以我们先换一个系列开始更新博客,就是现在这个经典的CNN复现啦(。・ ...
- JavaSwing实现的文本比较软件
先看效果:截图1 截图2: 实现思路: 1.界面UI设计 2.功能点 : a 打开文件进行比较 b 粘贴内容进去比较 c 提示帮助 d 窗口可以任意拖动 3.文本比较算法 java类 : ...
- H5-地理定位/本地存储/拖放
一.地理定位 Geolocation 兼容性:Internet Explorer 9+, Firefox, Chrome, Safari 和 Opera 支持Geolocation(地理定位). 一次 ...
- Servlet+JSP+JDBC综合案例
层级关系: 一.Util包 包里面写一个JDBCTools.java文件 功能:实现数据库连接返回一个Connection对象,并且可以实现数据库相应资源的关闭! 注意事项: 1.定义成员变量 1 p ...
- 关于Maven项目pom.xml文件不报错却有红叉的问题
原因:spring-boot,升级到2.1.5版本,而maven-jar-plugin.version插件默认版本不兼容所以报错,但不影响运行 解决:在<properties></p ...