Go to comments

HTML+CSS宝典 CSS基础 属性值的计算过程

一、简介

属性值的计算的过程这块知识网上搜不到,

在很多教程里面都没有出现,但是这块知识非常重要,他能让我们从更高的角度来看待,一个网页是如何渲染出来的。


属性值的计算的过程,

过程非常非常的复杂,其实讲的就是页面渲染的过程,浏览器是怎么把页面渲染出来的,这个过程是很复杂的里面有很多很多的细节。


但是对应我们来说,

了解它精简出来的最核心的点就可以了,了解这些核心点之后,对我们就非常非常有帮助了,我们再看页面的渲染,思路就会非常的清晰。


1、树形目录结构

首先说的一个点,

浏览器要渲染一个页面,是一个元素一个元素的依次渲染的,顺序按照页面文档的树形目录结构进行。


网页页面是树形的目录,目录的根节点是 <HTML> 元素,渲染的时候是从上到下,从父元素开始一个一个的渲染

1. 先渲染 HTML 元素,

2. 渲染 html 元素完成之后再渲染 head 元素,

3. head 元素渲染完成之后在渲染 meta 元素,在渲染 title 元素,这样依次渲染

4. 接下来渲染 body 元素,body 元素渲染完成之后渲染 h3 元素,在渲染 p 元素,在渲染 p 元素里面的 strong 元素,在渲染 a 元素,在渲染 img 元素

2019-05-17-12-27-14.png


这样一个一个元素渲染的,也就是说从树型结构的父元素(根元素HTML)开始依次进行渲染,这是它的整体的渲染过程,

但是这不是我们要学习的重点,我们要学习的是渲染每一个元素的时候,它是怎么渲染的?


2、渲染每个元素的前提条件

渲染每个元素的前提条件是,该元素所有的 css 属性必须有值。


就是说我们给一个元素写 css 属性的时候,不一定全部属性都写,只需要写几个想要设置的属性的就行了,

而实际上在渲染页面的时候,一个 css 属性没有值,元素是渲染不出来,都必须要全部有值,那 css 属性有多少呢?


css 属性有很多,我们打开一个网页(右键点击检查f12)

1. 随便选一个元素

2. 点击右边 computed 选项卡

3. 把 Show all 前进的钩选中(表示选中这个元素所有的css属性)

pic1618287909285176.png

这些属性必须要全部有值,只有全部有值了之后,才能代表这个元素方方面面的显示效果( 什么文字颜色,排列方式,文字大小,是否加粗,背景颜色等等… ),


每一个 css 属性代表一方面的样式,只有全部的 css 属性全部都确定下来,浏览器才知道这个元素该怎么显示,

而我们今天要学习的是,这些css属性是怎么全部出来的。


3、属性值计算过程简介

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


不是说我们写了哪些 css 属性,哪些 css 属性才有值,不是这样的,

页面上要显示的每一个元素,必须要全部的 css 属性全部有值,一个属性没有值都显示不出来。


这在一次说明了,在 HTML 核心语义化的时候学过,一个元素如果只有 HTML 是根本没法显示的,

显示全部要靠 css,哪怕我们一行 css 属性都没有写,浏览器也必须要算出所有的 css 属性值,只有算出来之后才能显示出来。


浏览器做了很的事情(这一点一定要理解)

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>渲染</title>
</head>
<body>
  <div>
    <textarea></textarea>
  </div>
</body>
</html>

1. 渲染的时候,先计算出 <HTML> 这个元素所有的 css 属性值,算出来过后渲染 HTML 元素(head元素不说了)

2. 在计算 body 元素所有的 css 属性值,再把 body 元素渲染出来

3. 然后在计算 div 元素所有的 css 属性值,再把 div 渲染出来

4. 在计算 div 里面的 textarea 元素所有的 css 属性值,再把 textarea 元素渲染出来

浏览器就是这样一步一步,渲染每一个元素的时候,都必须要把这个元素所有的 css 属性值全部算出来,全部算出来之后才能渲染。


我们今天学的就是浏览器是怎么计算的,

这个 css 属性是怎么从没有值到有值的,这块了解清楚后,就非常清楚之前学的 继承 和 层叠 是什么时候发挥作用的了。


一个html元素有很多的属性值,属性从一开始没有值,到最后每一个属性的值都确定下来,整个的过程叫做属性值的计算过程。

image.png


二、属性值的计算

属性值的计算有四个步骤

第一步确定声明值   样式表中没有冲突的声明,直接作为 css 属性值

第二步层叠冲突      对样式表有冲突的声明的使用层叠规则,确定 css 属性值

第三步使用继承      对仍然没有值的属性,若可以继承,则继承父元素

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

image.png


有一个 h1 元素,一开始所有的属性都没有值

1. 我们写了一些样式

2. 浏览器默认了一些样式

image.png


1、第一步:确定声明值

确定声明值意思是,参考样式表中( 作者样式表、浏览器默认样式表,只要是样式表都行 )没有冲突的声明,直接作为 css 属性的值


那些属性值是没有冲突的?

image.png

color: red

font-weight: bold

display: block

这三个属性是没有冲突的,没有冲突的属性,直接拿过来作为 css 的属性值 


属性值计算的过程第一步很简单,就是把那些没有冲突的属性声明,无论是浏览器默认样式,还是作者写的样式,

只要没有冲突就直接拿过来,非常非常的简单。


2、第二步:层叠冲突

层叠冲突,是对样式表有冲突的声明,使用 层叠规则 确定 css 属性值,

也就是说我们学习过的层叠发生在属性值计算过程的的第二步,

第一步做完之后才进行层叠


这时候看一下,哪些声明是有冲突的?

下面这些(带中滑线),声明是有冲突的,把这些声明进行层叠

image.png


怎么层叠呢( 之前学过的三步 )?

1. 比较重要性

 h1{display: block; font-size: 2em; font-weight: bold;}   把浏览器默认样式去掉了


2 比较特殊性

把特殊性比较小的去掉了

 .red{color:red; font-size:40px; }   类选择器去掉

 h1{ font-size:26px; }   元素选择器去掉

div h1.red{} 这个特殊性更高,有元素选择器,有类选择器,所以留下


3. 比较源次序

 div h1.red{ font-size:3em; font-size:30px;}   把前面的  font-size:3em;  去掉,源次序靠后的 div h1.red{ font-size: 30px; } 胜出

pic1618474761902253.png

这步完成之后,还有 css 属性没有值,这个时候进入第三步


3、第三步:使用继承

使用继承,对仍然没有值的属性,若可以继承,则继承父元素

1. 继承发生在经过了前面两个步骤之后,一些属性仍然没有值。仍然的意思是,前面已经有值的属性就不管了

2. 若可以继承,背景样式不能继承,文字属性可以继承

3. 这个时候才使用继承父元素的值,所以继承的时间点在层叠之后。


比如,

h1 的父元素有下面这些属性值(右边),哪些些属性值是可以继承过来?

image.png

1. font-size: 20px、font-weight: noraml  是不可以继承的,因为是对仍然没有值的属性,前面已经有值的就不管了

2. text-align  这个属性没有值,还跟文本相关,可以继承父元素的 text-align: center

3. background-color  属性也没有值,背景属性不能继承


因此这一步只改变了 text-align: center

image.png


继承层叠不冲突,因为继承发生的时间点是在层叠之后,

层叠的时候已经确定了属性值就不在使用继承了,换句话说已经声明了属性值就不使用继承了,

还有很多的 css 属性没有值,这个时候进入第四步。


4、第四步:使用默认值

第四步是个大杀器,对仍然没有值的属性,全部使用默认值。


比如说背景颜色 background-color 属性的默认值就是透明  background-color: transparent ,透明是一关键词 transparent

image.png

这样到了第四步,每一个 css 属性值全部都能确定了,因为每一个 css 属性都有默认值。


5、CSS 属性的默认值

mdn里面会告诉我们,每个属性的默认值是多少,

比如百度搜索关键词“width mdn”

https://developer.mozilla.org/zh-CN/docs/Web/CSS/width

 initial value(初始值)auto   width属性的默认值是auto,表示自动的


h1 元素什么样式都没有设置,他的宽度是多少?

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>H1元素宽度的默认值</title>
</head>
<body>

  <h1>Lorem</h1>

</body>
</html>

1. 选中h1元素

2. 点击 computed 表示计算过后,计算过后每一个属性都有值

3. 搜索 width 属性,这里算出的结果是1091px,当然这是根据自动值进行计算的

image.png

我们没有设置 width 属性,计算过后仍然是有值的,

再一次说明必须每个css属性都是有值的,浏览器才能确定怎么渲染。


6、面试问题

div 里面有

一个 a 元素,

一个 p 元素,

div 设置字体颜色为红色


字体颜色可以继承,问 a 元素是不是红颜色的?

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>面试题</title>
  <style>
    div{
      color: Red;
    }
  </style>
</head>
<body>

  <div>
    <a href="">举个例子</a>
    <p>p元素</p>
  </div> 

</body>
</html>

字体颜色是可以继承的,下面的 p 元素集成了是红颜色,为什么 a 元素字体的颜色没有继承?


搞清楚属性值计算的过程,p 元素属性值的计算过程

1. 第一步,确认声明值

    p 元素本身没有声明值(没有写过p元素的样式),没有声明值进入第二步

2. 第二步,层叠

    p 元素颜色没有设置,声明值都没有哪里来的冲突,第二步层叠也没有冲突

3. 第三步,继承

    第一步、第二步后,p元素颜色仍然没有值,要使用继承了。这个时候就可以把 red 颜色继承过来,所以 p 元素是红色的


a 元素属性值计算过程是怎么回事呢?

1. 第一步确定声明值,

    凡是在样式表写了样式就是声明了,a元素有声明值,在浏览器的默认样式表里面设置了颜色  color: -webkit-link 

image.png

2. 既然 a 元素有声明值,在第一步就确定颜色了,他也没有冲突,也不需要层叠,

    因此第一步,a元素颜色就已经确认了

3. 既然确定颜色了,就不需要继承了  color : red  杠划掉了,

    也就是说有了声明值,就不能继承了

这就是为什么 a 元素没有变化,因为在浏览器的默认样式表中 a 元素已经声明过了


五、两个特殊的CSS取值

inherit  手动(强制)继承,表示将父元素的值取出应用到该元素上

initial    初始值,将该属性设置为默认值


1、inherit

A 元素的小技巧

在写重置样式的时候,希望把 a 元素样式重置一下,怎么重置呢?

比如,希望a元素没有下划线,然后颜色继承父元素。


1. 没有下划线

希望a元素没有下划线简单,去掉下划线简单 text-decoration: none

第一步确定声明值,作者样式表和默认样式有冲突

第二步层叠冲突,重要性作者样式表胜出


2. 颜色继承父元素

希望颜色继承父元素,但是继承是发生在第三步的,前面两步已经把颜色确定下来,就不会发生继承了,

这个时候可以使用强制继承,这里可以声明一下颜色,颜色是什么不知道,反正来自父元素


强制继承写法是 color: inherit ,用一个单词 inherit 意思是继承

a{
  text-decoration: none;
  color: inherit; /* 强制使用父元素的值 */
}


这样 a 元素是红色的了,a 元素为什么是红色的了?

1. 第一步确认声明值,没有冲突颜色直接拿过去,

    color 已经有冲突了,color: inherit 第一步没有颜色不管

2. 第二步层叠冲突作者样式表 比浏览器的 默认样式表重要,作者样式表胜出,

    在第二步 color 属性就已经有值了,值是 inherit,值是来自父元素的颜色的值


渲染的过程是从上到下,所以父元素所有值已经确定下来了,用这个单词 inherit 去拿父元素的颜色值,

color 属性的颜色已经有值了,第三步的继承不会发生了


强制继承就是声明一个属性值 inherit ,

在一步确认声明值或者是第二步层叠冲突,完成属性值的确定,而不是等到第三步继承这个步骤在确定,相当于把继承给提前了。


 inherit 这个关键字的好处是,有些不能继承的属性也可以使用这个关键字,强制使用父元素的值

/*
  http://meyerweb.com/eric/tools/css/reset/ 
  v2.0 | 20110126
  License: none (public domain)
*/

html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, embed, 
figure, figcaption, footer, header, hgroup, 
menu, nav, output, ruby, section, summary,
time, mark, audio, video {
  margin: 0;
  padding: 0;
  border: 0;
  font-size: 100%; /* 可以理解为1em */
  font: inherit;
  vertical-align: baseline;
}
/* HTML5 display-role reset for older browsers */
article, aside, details, figcaption, figure, 
footer, header, hgroup, menu, nav, section {
  display: block;
}
body {
  line-height: 1; /* 行高是1 */
}
ol, ul {
  list-style: none;
}
blockquote, q {
  quotes: none;
}
blockquote:before, blockquote:after,
q:before, q:after {
  content: '';
  content: none;
}
table {
  border-collapse: collapse;
  border-spacing: 0;
}

/* 重置a元素 */
a{
  text-decoration: none;
  color: inherit;
}


2、initial

initial 初始值的例子

我们知道 background 背景颜色的默认是 transparent   background: transparent 

但是有些属性不知道他的默认值是什么,这个时候只需要使用一个关键字 initial,表示直接使用这个属性的默认值  background: initial 

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>initial初始值</title>
<style>
  div {
    width: 100px;
    height: 100px;
    background-color: Red;
  }
  .mydiv {
    background-color: initial; /* div默认背景又是透明的了 */
  }
</style>
</head>
<body>

  <div class="mydiv"></div>

</body>
</html>




Leave a comment 0 Comments.

Leave a Reply

换一张