Code前端首页关于Code前端联系我们

CSS选择器优先级(特异性)的计算规则,特殊情况

terry 2年前 (2023-09-27) 阅读数 66 #数据结构与算法

什么是选择器优先级(特异性)

直接复制MDN对优先级的定义:

浏览器通过Priority来确定哪些属性值​​对元素最重要,然后将这些属性值用于元素。优先级是基于由不同类型的选择器组成的匹配规则。

这句话也很抽象,暂且忽略吧。不过我们可以先看一个例子:

  • HTML:
<div id="content" class="content">
我是什么颜色
</div>
复制代码
  • CSS:
#content {
    color: #f00;
}
.content {
     color: #0f0;
}
复制代码

最终文本的颜色是什么?答案很简单:红色。这就涉及到一个优先级的问题。对于相同的内容,我们使用ID选择器类选择器,因为ID选择器的优先级高于类选择器 ,所以最终显示红色的。

优先级计算规则

想必每个写过CSS的朋友都知道,CSS选择器的优先级关系是:

In Row > ID Selector > Class Selector > Tag Selector。

浏览器特殊的优先级算法是什么?也许还有人不知道。算法的流程在《CSS REFACTORING》中提到。

通过将数字插入 (a, b, c, d) 来确定特异性:

  1. 如果通过 style 属性应用样式,则 a=1;否则 a=0.
  2. b 等于存在的 ID 选择器的数量。
  3. c 等于存在的类选择器、属性选择器和伪类的数量。
  4. d 等于存在的类型选择器和伪元素的数量。

翻译为

优先级由 A 确定, B, C, D 由值指定​​​​​​,这些值根据以下计算:

  1. 如果有内联样式,则A = 1,否则A = 0;值
  2. B等于ID选择设备出现次数;值
  3. C 等于 类选择器 属性选择器 伪类 总出现次数s; 值D 为等于标签选择器 和伪元素 出现的总次数。也 好像还是直接这样理解,那就先上个例子:
    #nav-global > ul > li > a.nav-link
    复制代码

    用上面的算法求 a B C值 D :

    1. 由于没有内置样式,A = 0;选择器
    2. ID总共出现一次,B = 1
    3. 类选择器出现1次,属性选择器出现0次,伪类选择器出现0次,所以C = (1 + 0 + 0) = 1;标签选择器出现了3次,伪元素出现了0次,所以D = (3 + 0) = 3 ;

    计算出来上述ABCD可缩写为: (0, 1 , 1, 3)

    为了熟悉优先级算法,我们来做一些练习:

    li                                  /* (0, 0, 0, 1) */
    ul li                               /* (0, 0, 0, 2) */
    ul ol+li                            /* (0, 0, 0, 3) */
    ul ol+li                            /* (0, 0, 0, 3) */
    h1 + *[REL=up]                      /* (0, 0, 1, 1) */
    ul ol li.red                        /* (0, 0, 1, 3) */
    li.red.level                        /* (0, 0, 2, 1) */
    a1.a2.a3.a4.a5.a6.a7.a8.a9.a10.a11  /* (0, 0, 11,0) */
    #x34y                               /* (0, 1, 0, 0) */
    li:first-child h2 .title            /* (0, 0, 2, 2) */
    #nav .selected > a:hover            /* (0, 1, 2, 1) */
    html body #nav .selected > a:hover  /* (0, 1, 2, 3) */
    复制代码

    好的,现在我们已经弄清楚了优先级是如何计算的。但问题仍然出现,如何比较两个优先级? 比较的规则是:从左到右比较,较大者为胜。如果相同则继续向右移动一位进行比较。如果 4 位都相同,则后者将覆盖前一个

    我们再看一下示例:

    • html:
    <div class="nav-list" id="nav-list">
    	<div class="item">nav1</div>
    	<div class="item">nav2</div>
    </div>
    复制代码
    • CSS:
    #nav-list .item {
    	color: #f00;
    }
    
    .nav-list .item {
    	color: #0f0;
    }
    复制代码

    计算优先级 #nav-list .item 优先级 ( 0, 1, 1, 0), .nav-list .item(0, 0, 2, 0) 。左边第一个数字都是0。看左边第二个数字。第一个是1,第二个是0,所以(0, 1, 1, 0)大于(0, 0 , 2, 0),即 # nva-list .item.nav-list .item大,所以字体会是红色。

    优先级的特殊情况

    根据上面的优先级计算规则,我们可以知道内联样式的优先级是最高的,但是有没有办法让外部样式覆盖内联样式呢?是的,然后!重要采取行动。由于内联样式一般很少使用,所以!important也很少使用!如果您不想覆盖内联样式,建议不要使用!重要

    可能有人会想,如果我在内联样式中使用了!important,那外层样式就不能做什么了吗?例如,以下代码:

    • HTML:
    <div class="app" style="color:#f00!important">666</div>
    复制代码
    • CSS:
    .app {
    	color: 0f0!important;
    }
    复制代码

    是的,你赢了。这时,内置样式就已经强大到你无法覆盖它,无论你怎么写外部样式。在实际代码中应该避免这种情况!请记住,切勿在内联样式中使用 !重要

    。最后,!重要真的是无敌王者吗?其实不是,在某些情况下我们可以超过!重要的是,请参见以下示例:

    • html:
    <div class="box" style="background: #f00; width: 300px!important;">我的宽度是多少呢??<div>
    复制代码
    • css:
    .box {
    	max-width: 100px;
    }
    复制代码

    当前宽度为。 box 只有100px而不是300px,可以看到max-width可以超过宽度!重要!但这并不是真正的优先事项。问题在于优先级与相同的属性进行比较,而 max-widthwidth 是两个不同的属性。我举这个例子的原因是为了让大家知道,有时候无论你如何设置容器width它都不起作用。检查是否有人写了 max-width 来欺骗你。

    作者:zhanyuuzhang
    来源:掘金

版权声明

本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。

热门