css属性值计算过程

218 阅读5分钟

渲染元素的前提条件

元素被渲染的前提条件:该元素的所有css属性都有值

一个元素的所有css属性值可以通过控制台的computed选项卡进行查看

image.png

css表现

在编码过程中,有时候会碰到某一个元素的样式表现和我们的预期是不符合的,此时可以查看控制台的computed选项卡查看该元素的最终样式值,那computed中的css属性又是怎么生成的呢?

先来看一个简单的样式案例

代码:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>css 属性计算过程</title>
    <style>
      .main {
        color: red;
      }
    </style>
  </head>
  <body>
    <div class="main">
      <a href="">a标签</a>
      <p>p标签</p>
    </div>
  </body>
</html>

表现:

image.png

疑问:

都作为.mian下的子元素,为什么p标签和a标签的表现形式不一样???

属性值计算过程

概念

一个元素从所有属性都没有值到所有属性都有值的这个过程,就叫属性值计算过程

image.png

计算过程步骤:

  1. 确定声明值:参考样式表中没有冲突的声明,作为css属性值
  2. 层叠冲突:对样式表有冲突的声明使用层叠规则,确定css属性值
  3. 使用继承:对仍然没有值的属性,若可以继承,则继承父元素的值
  4. 使用默认值:对仍然没有值的属性,使用默认值

案例分析

不同的浏览器都有一套自己的默认样式表

首先我们来看一下谷歌浏览器中h1的默认样式值(样式后有user agent stylesheet就是浏览器默认样式值) image.png

接下来我们用一个案例代码来梳理一下css的属性值计算过程

 <style>
      .h1style {
        color: red;
        font-size: 12px;
      }
      h1 {
        font-size: 12px;
      }
      div h1.h1style {
        font-size: 16px;
        font-size: 20px;
      }
</style>

<div>
      <h1 class="h1style">案例分析</h1>
</div>

第一步、确定声明值

参考样式表中没有冲突的声明,作为css属性值(确定作者样式表和浏览器默认样式表中无冲突的属性的属性值)

样式表:作者样式表、浏览器默认样式表(user agent stylesheet)

image.png

第二步、层叠冲突

对样式表有冲突的声明使用层叠规则,确定css属性值,我们通常说的比较选择器的权重其实是发生在层叠冲突的第二步的

  1. 比较重要性(作者样式表高于浏览器默认样式表)
  2. 比较特殊性(比较权重)
  3. 比较源次序(比较书写顺序,代码靠后的覆盖代码靠前的)

image.png

使用继承

对仍然没有值的属性,若可以继承,则继承父元素的值(eg:文字属性)

可在 MDN CSS 属性参考页面的“形式定义”技术信息框中查看属性能否被继承

image.png

继承和层叠是不冲突的,继承发生在层叠之后

使用默认值

对仍然没有值的属性,使用默认值

可在 MDN CSS 属性参考页面的“形式定义”技术信息框中查看默认值数据

image.png

补充内容

可继承的属性

在 MDN CSS 属性参考页面,有一个名为“形式定义”的技术信息框,其中列举了属性的很多数据信息,包括能否被继承。以 color 属性的形式定义部分为例。

image.png

可继承的属性大致归类如下:

  1. 字体属性:font、font-style、font-variant、font-weight、font-size、line-height等属性是字体样式的属性,都可以被子元素继承。
  2. 文本属性:color、text-indent、text-align、text-decoration、text-transform、letter-spacing、word-spacing等属性也是可以被子元素继承的属性。
  3. 元素可见性:visibility属性可以被子元素继承,它可以将元素隐藏起来,但不会改变网页的布局。
  4. 表格属性:border-collapse、border-spacing、caption-side、empty-cells等表格属性也是可继承属性。
  5. 列表属性:list-style、list-style-type、list-style-position等列表属性也可以被子元素继承,用于设置无序列表和有序列表的样式。
  6. 其他属性:cursor、direction、unicode-bidi、outline、quotes、pointer-events等一些其他的属性也是可继承属性。

回看疑问

现在我们再来看一下上面提到的疑问

 <style>
      .main {
        color: red;
      }
    </style>
  </head>
  <body>
    <div class="main">
      <a href="">a标签</a>
      <p>p标签</p>
    </div>
  </body>

谷歌浏览器的默认样式表中

a的默认样式值:

image.png

p的默认样式值:

image.png

  1. 确定声明值

没有直接对a和p进行样式定义,所以浏览器默认样式中的属性都没有冲突,直接取浏览器默认样式值,此时可以确定a的color属性的值为浏览器默认样式值

  1. 层叠冲突

a和p都没有样式冲突的属性,直接进入第三步

  1. 使用继承

color是可继承的属性,p的父级.main定义了color属性,所以p继承,确定了color属性值为red

  1. 使用默认值

剩下的没有属性值的属性使用默认值

这就是a标签和p标签css样式表现不一致的原因。

如何修改可以让a标签的颜色和p标签的一致呢?

 a {
     color: inherit;
  }

上述代码添加后,第一步,color就是有冲突的属性值,没法直接确定了,进入第二步层叠冲突,作者样式表高于默认样式表,确定color属性值为继承来的父级的color值