CSS的三大机制

CSS的三大机制是:特殊性、继承、层叠。样式最终的呈现由层叠机制决定,但层叠与特殊性、继承又有关系。换句话说,一个元素某一样式要应用那个值,用户代理需要考虑继承,考虑声明的特殊性,考虑声明本身的来源,而这个过程就叫做层叠。本文的理论均基于CSS2.1。

特殊性

CSS样式规则

CSS样式是由多条规则组成,每条规则由分为选择器组和声明块。顾名思义,选择器组是多个选择器分组的集合,而声明块则是由多条声明组成的。很多时候多条声明会选中同一个元素,声明的的属性一样,但属性值却不一致,这里就存在一个冲突。显然,最终元素只能有一个冲突的样式能够生效,但是,生效的是哪个样式呢?用户代理是通过什么来进行判定的呢?(好吧,其实上面也简单提到:一个元素某一样式要应用那个值,用户代理需要考虑继承,考虑声明的特殊性,考虑声明本身的来源)要弄清楚这个问题,特殊性是避不开的。

什么是特殊性

所谓的特殊性,其实是CSS样式一种计算声明权重的规则。特殊性是由规则的选择器确定的,然后用户代理会将计算出来的特殊性附加给相应的每一个声明上。

如何计算/比较选择器的特殊性

特殊性可以分成五个部分的权重:

  • 内联样式
  • id选择器
  • 类名选择器、属性选择器、伪类
  • 元素、伪元素
  • 通配符(*)(先指出统配符的权重为0)
    以上五部分权重依次减少
    因为通配符对特殊性没有贡献,所以计算特殊性,就是计算前四部分的贡献。
    计算方法:
    统计相应选择器出现的个数填入对应的部分,
    例如内联样式就相当于[1,0,0,0],
    p a 就相当于[0,0,0,2]。
    统计好后就可以比较不同选择器的权重了。
    比较是按照上面权重的顺序比较下来,先看看内联样式,一个是内联样式,另一个不是内联样式,那么肯定是内联样式的特殊性高了。
    如果内联样式比较不出来,就比较id选择器的数量,数量多的一方特殊性高,
    如此依次往下。
    很多人也许看出来了,权重的顺序是从上到下依次比较,只要上面的权重较大,后面的选择器不管数量有多少都不会对权重的比较造成影响了。这里没有遵循量变引起质变的哲学思想,好像展示的是一种阶级固化,强者恒强的思想。不过显然,这样计算权重也会更加方便。
    这也是为什么十几个元素的选择器也不会比一个类名的选择器的权重更高,事实上就算有更多数量的元素但不含其它选择器的选择器也不会比一个类名选择器的权重要高。

声明的特殊性

用户代理要判断每条声明的权重,因此会将CSS样式的每个声明都附加其选择器的特殊性。这样每条声明就有唯一的一个特殊性了。

继承

CSS还有一个继承机制,即样式不仅会应用到指定的样式,而且会应用到其后代的元素。

文档结构

上面提到了一个后代的概念,指的是文档元素之间的一种关系。HTML文档的元素是具有层次结构的,html元素为根元素,其余的元素均是挂载在其上。这些元素可以以一种树形的结构表示出来,元素的直接上级为父,直接下级为子,同父级的元素为兄弟元素,元素a若可以通过若干个元素(包括这个元素本身)的父元素联系到另一元素b,则元素a为元素b的后代,相对的元素b为元素a的祖先。

继承的机制需要注意的点

  • 并不是所有的属性都可以继承,一般的,大多数框模型属性(包括外边距、内边距、背景、边框)都不能继承。
  • 继承的值没有特殊性
    不知道大家对上面提到的统配符的特殊性还有没有印象,通配符的特殊性是0,但继承的值并不是0,而是连0特殊性都没有!上面提到统配符对特殊性没有贡献,但是哪怕是通配符,权重也是要高于继承的值的,所以通配符可以可以短路继承的效果,即如果继承的值与通配符选中的元素(所有元素都会被通配符选中)设置的值冲突时,继承的值将被通配符设置的值覆盖。
    扩展开来:如果某个元素被选择器选中设置了样式,那么继承的冲突声明就会失效。
    这一点经常遇到,如在导航栏上设置了字体颜色,但我们往往会预设了a元素的颜色,这时在导航栏设置的颜色就无法在a元素上生效了。

层叠

样式的呈现只有一种效果,而仅仅通过特殊性来决定权重并不能完全解决冲突。想象一下,如果两条作用于同一元素的声明,它的特殊性相同,也就是它们的权重相同时,浏览器应该用哪一条声明呢?这个就与CSS的层叠机制有关了。

CSS样式来源

在介绍层叠规则前,先介绍一下CSS样式的来源。CSS样式的来源可以分为3中:用户代理默认样式、创作人员、读者样式。

层叠的规则:

  1. 将书写的样式拆成一条条独立的声明,每条声明都一个包含给定元素的选择器
  2. 按照CSS样式来源对声明权重排序(从上到下,权重越来越小):
    1. 有!important标志的读者声明
    2. 有!important标志的创作人员声明
    3. 没有!important标志的创作人员的声明
    4. 没有!important标志的读者样式声明
    5. 用户代理的默认样式声明
      (注意,这部分是我的个人理解,不排除理解错了)这里的排序应该是和特殊性权重的排序一样,层级间的权重是不可逾越的。也就是说用户代理的默认样式声明不管他怎么写,都不会比没有!important标志的读者样式声明权重高,而没有!important标志的创作人员的声明也永远高于没有!important标志的读者样式声明。
  3. 如果按照来源排序后,一个元素的有声明冲突,这时就要按照特殊性给声明排序了。注意排序时是先来源后特殊性,也就是说是在来源排序后声明没有冲突就没有后面的排序了,该样式可以直接确定了。
  4. 如果特殊性后声明还有冲突,那么就比较样式出现的顺序。这时就要看声明出现在样式表中的位置了。它在文档或者样式表中越后出现,权重就越高,即后面的样式“层叠”了前面的样式。如果样式表中有导入的样式表,一般认为出现在导入样式表的声明在前,主样式表中的所有声明在后。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值