Go to comments

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

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


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


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


首先说的一个点,

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


一、树形目录结构

网页页面是树形的目录,目录的根节点是<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)开始依次进行渲染,这是它的整体的渲染过程,

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


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

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


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

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


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

1. 随便选一个元素

2. 点击右边 computed 选项卡

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

pic1618287909285176.png

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


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

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


三、属性值计算过程简介

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


不是说我们写了哪些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{} 这个特殊性更高,有元素选择器,有类选择器,所以留下

pic1618474761902253.png

3). 比较源次序:div h1.red{font-size:3em; font-size:30px;}  把前面的font-size:3em; 去掉,

                         源次序靠后的  div h1.red{ font-size: 30px; }  胜出


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


3、第三步:使用继承

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

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

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

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


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

image.png

1). font-size: 20pxfont-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元素属性值的计算过程

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

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

第三步:继承             第一步、第二步后,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初始值的例子

<!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>

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

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



Leave a comment 0 Comments.

Leave a Reply

换一张