[css]继承关系(一)

一、概述

一个元素最终只有一个css属性对其生效,除了多处指定属性这种情况,还有一种就是元素会继承祖元素的属性,这是一个不简单,也不复杂的问题。

二、继承

一个元素如果本身没有被指定css属性,那么它就会继承父元素的属性,继承是链式的,元素会向上查找,直到遇到指定样式的祖元素,并且继承它的属性:

<style>
    body{
      font-family: cursive;
    }
    div{
      font-family: monospace;
    }
    </style>
</head>
<body>
    <p>p</p>
    <div>div</div>
    <div><span>div->span <font>div->span->font</font></span></div>
</body>
  • 元素『p』没有指定font-family属性,往上遍历继承了『body』的font-family属性;
  • 元素『div』指定了自己的font-family属性,没有再往上遍历;
  • 元素『span』没有指定font-family属性,往上遍历继承了『div』的font-family属性
  • 元素『font』没有自己的font-family属性,往上遍历『span』也没有自己的样式,于是继续遍历,最终继承了『div』的font-family属性

1.通过元素名称来指定的属性会被其本身和本身的子元素继承:

body {
    font-family: cursive;
}

通过指定『body』元素的样式,所有属于『body』的后代元素都会继承这个样式(一些老旧版本浏览器除外

2.单独指定元素属性可以摆脱继承:

<style>
    body{
      font-family: unset;
    }
    div{
      font-family: serif;
    }
</style>
<body>
    <div>div</div>
</body>

现在『div』拥有了自己的font-family属性,不再继承『body』的font-family属性

 3.多重路径指定

先来看看一段声明:

<style>
    div span font{
      font-family: unset;
    }
    body div font{
      font-family: serif;
    }
    span font{
      font-family: serif;
    }
    font{
      font-family: fantasy;
    }
</style>
<body>
    <div><span>div->span<font>div->span->font</font></span></div>
</body>

以上所有声明都指向了『font』元素的情况下,究竟最终会是哪个生效?

通常选择器的优先级遵循以下规则:

  • 更详细的选择器优先级更高,所以无论是『body font』还是『span font』都比『font』的优先级更高,同理『body div font』比『span font』优先级更高;
  • 同详细的选择器,最后的一个声明会覆盖上面的声明,如同上述例子中,『div span font』与『body div font』中,后者的优先级是最高的,它覆盖了前者;

三、选择器的优先级

css中有3种元素选择器,2种元素指明后缀,如果声明被重叠,那么优先级更高的选择器会覆盖优先级别更低的声明,这也是影响元素样式继承的一个因素;

 

类型 优先级(数字越大优先级越高) 示例
 派生选择器  1
div{...}
ul li{...}
h1 > strong {...}
li + li {...}
 类选择器  2
.foo{...}
 类指明后缀  2
div.foo{...}
 属性指明后缀  2
div[title="1"]{...}
  id选择器  3
#bar{...}

1.元素选择器

举个例子:

<style>
    .c-2 .c-3{
      font-family: serif;
    }
    span .c-3{
      font-family: serif;
    }
    </style>

</head>
<body>
    <div class="c-1"><span class="c-2">div->span <font class="c-3">div->span->font</font></span></div>
</body>

示例中,尽管『span .c-3』的路径跟『.c-2 .c-3』一样详细并且在『.c-2 .c-3』的下面,但是由于类选择器的优先级比派生选择器的优先级更高,所以『.c-2 .c-3』是最终生效的样式。

同理,如果给示例增加『.c-1 .c-2 .c-3』和『.c-1 span .c-3』两个声明,最终生效的也只会是『.c-1 .c-2 .c-3』。

2.元素指明后缀

给一个选择器加上一个指明后缀,的继承优先级,等价这个选择器后面接一个类选择器:

<style>
    font[title="1"]{
      font-family: serif;
    }
    span font{
      font-family: serif;
    }
</style>
<body>
    <div title="1" class="c-1" id="i_1"><span class="c-2">div->span<font class="c-3 c-3-1" id="i_1" title="1">div->span->font</font></span></div>
</body>

所以上述例子『font[title="1"]』的优先级是比『span font』要高的;

根据以上规则,同路径长度同级的声明,后面的声明会覆盖前面的声明:

<style>
    .c-2 .c-3{
      font-family: serif;
    }
    .c-3[title="1"]{
      font-family: serif;
    }
    .c-3.c-3-1{ 
      font-family: serif;
   }
</style> <body> <div title="1" class="c-1" id="i_1"><span class="c-2">div->span<font class="c-3 c-3-1" id="i_1" title="1">div->span->font</font></span></div> </body>

示例中『.c-2 .c-3』和『.c-3[title="1"]』和『.c-3.c-3-1』是等价的,所以最终生效取决于谁声明在最后,这里是『.c-3.c-3-1』;

 

总结

每一个选择器类编都有它自己的优先级等级,它们不会被具有较低优先级的选择器覆盖。例如,权重为一百万的类选择器不会覆盖权重为一的 ID 选择器。评估优先级的最佳方法是对不同的优先级等级单独进行评分,并从最高的等级开始,必要时再计算低优先级等级的权重。即,仅当某一列的优先级权重相同时,你才需要评估下一列;否则,你可以直接忽略低等级的选择器,因为它们无法覆盖高优先级等级的选择器。

例如这个例子:

<div id="i_1" class="s-1">
      <span id="i_2" class="s-2">
        hahaha.
      </span>
</div>

以下这个css中,<.s-1 #i_2>会覆盖<#i_1 .s-2>因为它们被认为是相同的优先级,所以最后一条语句覆盖上面的语句:

<style>
      #i_1 .s-2{color: red;}
      .s-1 #i_2{color: sienna;}
</style>

但是如果把<.s-1 #i_2>改写成<#i_2>,则<#i_1 .s-2>生效,因为<#i_1 .s-2>优先级比<#i_2>高:

<style>
      #i_1 .s-2{color: red;}
      #i_2{color: sienna;}
</style>

用表格来统筹它们的优先级是如何比较的:

选择器 ID 元素 优先级
#i_1 .s-2 1 1 0 1-1-0
.s-1 #i_2 1 1 0 1-1-0
#i_2 1 0 0 1-0-0
posted @ 2020-05-08 16:08  yiyide266  阅读(778)  评论(0编辑  收藏  举报