《 架构师重学前端》CSS疑难点

282 阅读6分钟

em相对大小

不同的属性使用em单位时有不同的效果

font-szie属性

相对于父级元素的字体大小来计算的

<style>
    .box {
        font-size: 12px;
    }

    .text {
        font-size: 2em;
    }
</style>

 <div class="box">
     <div class="text">我是文本内容</div>
</div>

这里 font-size: 2em;也就等同于font-size: 24px;

其他属性

<style>
    .box {
        font-size: 12px;
    }

    .text {
        font-size: 2em;
        line-height: 3em;
    }
</style>
 <div class="box">
     <div class="text">我是文本内容</div>
</div>

上面已经说明.textfont-size: 24px;

但是这样要注意line-height: 3em;并不是 line-height: 36px;,而是line-height: 72px;,因为line-height属性是根据当前元素的font-size来计算的

空格与换行

<div class="text">
    我是文本内容    第一行
    我是文本内容 第一行
</div>

image-20240526182053551

不难发现,在HTML中无论是换行还是空格,也无论换几行和空几个,最后在代码中所表现的都是一个空格

那要如何实现多个空格与换行呢?

&nbsp;</br>

<div class="text">
    我是文本内容&nbsp;&nbsp;&nbsp;&nbsp;第一行
    </br></br>
	我是文本内容 第一行
</div>

image-20240526182457731

white-space

这里要注意一下,在html文件中的换行其实是通过文档的*\n*和普通的空格实现的

white-space的作用就是如何处理空格和文档转义符

<div class="text" style="white-space: pre;">
    我是文本内容 		第一行

    我是文本内容 第一行
</div>

image-20240526183308219

具体属性值,参考MDN文档

</br>\n

</br>

作用于HTML文档中,也就是HTML标签中的一种

<div class="text">
    我是文本内容 第一行</br>我是文本内容 第一行
</div>

\n

image-20240526183927157

从文档层次解析,其实红色框的位置应该存在*\n*字符

这里要特别记住,textarea中的内容换行的换行是*\n*

自适应关键字

在CSS3新增属性值中fill-available、max-content、min-content、fit-content

fit-content

尺寸按照内容自适应

注意:虽然行内元素也能实现内容自适应,但是行内元素是没有宽度的,fit-content属性值是有宽度的

<style>
    main {
        width: 100vw;
        background-color: red;
    }

    main div {
        background-color: yellow;
        width: fit-content;
        margin: auto;
    }
</style>
<main>
    <div>我是文本内容</div>
</main>

image-20240526200757978

如果使用行内元素,显示margin: auto;会失效

min-content

尺寸取决于内部元素中最小尺寸值中最大的那个元素的尺寸作为最终容器的尺寸

元素的最小宽度

替换元素

例如 img 标签,如果 img 标签没有固定数值,其宽度取决于图片的宽度,所有 img 的最小宽度就是图片的宽度

文本元素的最小宽度值

这里文本元素指包裹了文字的元素,如果是中文,本身没有固定值下,一个字就是最小宽度值,而如果是英文,由于英文不会自动换行,所以包裹了英文的元素的最小宽度值就是整句英文的宽度( 可设置 word-break 改变最小宽度 )

固定值的最小宽度值

如果一个元素设置了固定的宽度值,那么其最小宽度自然就是其自身的宽度值

案例解析

<style>
    main {
        background-color: red;
        width: min-content;
    }

    div,
    img {
        margin-bottom: 20px;
        background-color: yellow;
    }
</style>
<main>
    <div>我是中文的</div>
    <div>hellowordppppptptptpyoyyy</div>
    <img src="./tp.png" width="100" />
</main>

image-20240526202818682

main元素的最小宽度按照是单词行,因为英文的最小宽度是按照单词

<style>
    main {
        background-color: red;
        width: min-content;
    }

    div,
    img {
        margin-bottom: 20px;
        background-color: yellow;
    }
</style>
<main>
    <div>我是中文的</div>
    <div>hello word</div>
    <img src="./tp.png" width="100" />
</main>

image-20240526203109536

这里的最小宽度是图片

flex中的min-content

flex-basis: 0%;并不是真正的0%,而是和flex-basis: min-content;一样的值

max-content

其尺寸决于内容,内容有多大尺寸就有多大

<style>
    main {
        background-color: red;
        width: max-content;
    }

    div,
    img {
        margin-bottom: 20px;
        background-color: yellow;
    }
</style>
<main>
    <div>我是中文的我是中文的</div>
    <div>hello word</div>
    <img src="./tp.png" width="100" />
</main>

image-20240526214354187

fill-available

能让设置了此值的元素自动填满剩余空间,跟默认 div 类似

<style>
    main {
        background-color: red;
        width: fill-available;
    }

    div,
    img {
        margin-bottom: 20px;
        background-color: yellow;
    }
</style>
<main>
    <div>我是中文的我是中文的</div>
    <div>hello word</div>
    <img src="./tp.png" width="100" />
</main>

image-20240526214822971

但这里需要注意,fill-available兼容性很差,并且在不同浏览器的属性名称还不一样,所以尽量不要使用

渲染树生成过程

首先要知道浏览器需要Dom树CSS树结合才能渲染出页面的

DOM树指的是HTML结构中多个标签形成的树级结构,每个DOM标签就是树的节点,HTML标签一般是根节点

CSS树 的结构和DOM树结构是一样的,但是这里需要注意,每个标签都要有完整的样式

浏览器渲染页面是从上到下依次进行的,从树结构来看就是从根节点开始到叶子节点

这里可能就会有疑问:样式属性有成千上万,不可能每个属性开发者都定义了,开发者没有定义的属性是如何拥有值的?

这里就需要讨论CSS树节点是如何生成样式

<style>
    
    /* 来自浏览器默认样式表 */
    h1 {
        display: block;
        font-size: 2em;
        margin-block-start: 0.67em;
        margin-block-end: 0.67em;
        margin-inline-start: 0px;
        margin-inline-end: 0px;
        font-weight: bold;
        unicode-bidi: isolate;
    }
    
    main {
        color: yellow;
        background-color: orange;
        text-align: center;
        font-size: 20px;
        font-weight: lighter;
    }

    h1 {
        font-size: 26px;
    }

    .m-h1 {
        color: red;
        font-size: 50px;
    }

    h1.m-h1 {
        font-size: 60px;
        font-size: 30px;
    }
</style>
<main>
    <h1 class="m-h1">我是h1标签</h1>
</main>

其实不止开发者自行定义的样式表,浏览器对于每个标签也有不同的样式,从这里也可以看出为什么h1标签默认就有加粗、外边距,这都是因为浏览器默认的样式表

image-20240606232223289

了解了前置知识,现在可以开始讨论每个标签的样式生成原理了

注:这里只讨论h1标签

  1. 处理单一样式声明(开发者自定义样式、浏览器默认样式)。只处理唯一样式表样式,也就是不考虑样式冲突和继承

    /*  第一阶段h2标签添加的属性样式 */
    
    display: block;
    margin-block-start: 0.67em;
    margin-block-end: 0.67em;
    margin-inline-start: 0px;
    margin-inline-end: 0px;
    font-weight: bold;
    color: red;   
    
  2. 处理冲突样式。多个选择器中共同出现的样式会产生冲突,按照以下规则解决冲突

    1. 重要性:开发者自定义样式>浏览器默认样式
    2. 特殊性:权重高的选择器优先
    3. 原次序:相同权重的属性,按照先后顺序
    /*  第二阶段h2标签添加的属性样式 */
    
    font-weight: lighter;
    font-size: 30px;
    
  3. 处理继承样式。如果样式可以继承,就会从父标签继承样式

    /*  第三阶段h2标签添加的属性样式 */
    text-align: center;
    
  4. 处理默认样式。

    image-20240606234424793

重点:如果某个属性在其中一个阶段就已经被赋予属性值,那么就不会再参与到其他阶段的规则中

inherit属性值

inherit属性值代表该属性来自于继承,会提前第一阶段就发生继承获取值

比如h1设置 color: inherit;

h1{
    color: inherit;
}

那么在第一阶段就会变成

h1{
    color: yellow;
}