深入理解CSS | 青训营笔记

133 阅读11分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第2天。

一、本堂课重点内容

  • CSS简介
  • CSS工作原理
  • CSS选择器
  • 常见CSS属性
  • 浏览器渲染页面原理
  • 盒模型
  • 布局

二、详细知识点介绍

CSS选择器

属性选择器

通过[属性名]进行选择,前面可跟id,标签,类名等。

[attribute="value"] 选择器用于选取带有指定属性和值的元素。

[attribute~="value"] 选择器选取属性值包含指定词的元素。

[attribute|="value"] 选择器用于选取指定属性以指定值开头的元素。值必须是完整或单独的单词,比如 class="top" 或者后跟连字符的,比如 class="top-text"。

[attribute^="value"] 选择器用于选取指定属性以指定值开头的元素。值不必是完整单词!

[attribute$="value"] 选择器用于选取指定属性以指定值结尾的元素。值不必是完整单词!

[attribute*="value"] 选择器选取属性值包含指定词的元素。值不必是完整单词!

伪类选择器

状态伪类, 元素的特定状态,如:link,:visited,:hover,:active,:focus

结构性伪类,根据dom节点在dom树中出现的位置决定是否选中,如first-child,last-child

组合选择器

  • 直接组合(无空格),AB,同时满足AB
  • 后代选择器 (空格),A B,B是A的所有后代
  • 子选择器 (>),A > B,B必须是A的直接子元素
  • 相邻兄弟选择器 (+),A + B,A与B同级,且B在A后面
  • 通用兄弟选择器 (~),A ~ B,A与B同级,且B紧跟在A的后面
  • 选择器组(,),多个选择器同时满足,,分隔每一个选择器

常见属性

颜色

rgb(3个0到255的数),hsl(色相为0到255的数,饱和度和亮度为百分数),都可以加第4个参数透明度

字体

font-family

用font-family设置字体类型,用,分隔开的多个值,最后一个是默认风格。

  • serif 衬线体
  • sans-serif 无衬线体
  • cursive 手写体
  • fantasy 花里胡哨的字体
  • monospace 等宽字体

font-weight: 加粗程度,400为normal,700为bold,可设置100-900

line-height: 行高,无单位的值表示行高为字体大小的倍数

text-align: 文本对齐,text-align: justify两端对齐,最后一行不生效。

letter-spacing:字符之间的间距

word-spacing:单词之间的间距

text-indent:首行缩进

空白符的处理

white-space属性:

  • normal自动换行,合并多个空格;
  • nowrap强制不换行,合并多个空格,出滚动条;
  • pre保留换行,保留所有空格,出滚动条;
  • pre-wrap自动换行,但保留所有空格;
  • pre-line保留换行,但合并空格;

选择器优先级

id > (伪)类 > 标签

继承

CSS中与文字相关的属性可继承,如color,font-size。

与盒模型相关的不可继承,如div的宽度width不可继承。但是可以显式的从父级继承,如box-sizing:inherit;

初始值

CSS中,每个属性都有一个初始值,如background-color初始值萎transparent,margin-left初始值为0。可以使用backgroune-color:initial;显式重置为初始值。

CSS求值过程

CodePen - 青训营/CSS/取值过程 (cdpn.io)

  • 解析HTML为dom树,解析样式,link、style等,统称样式规则
  • 遍历所有的元素,获得所有元素的CSS属性值,每一个元素的每个属性都要经历以下过程
  • filtering,筛选规则,对于当前的dom元素,看看选择器是否匹配,找到能够匹配到元素的选择器,得到一组规则,称为声明值。声明值可能有0或多个
  • cascding,根据优先级,确定优先级最高的属性值,称为层叠值。根据来源、!important、选择器特异性、书写顺序等
  • defaulting,层叠值为空时,则采用继承或初始值,称为指定值。指定值一定不为空
  • resolving,将一些相对值转化为绝对值,称为计算值。计算值是浏览器在不进行实际布局的时候,得到的最精确的值
  • formatting,将计算值进一步转换,如关键字,百分比等转为绝对值,称为使用值。不会再有相对值或关键字
  • constraining,取整,考虑约束,如max-width等,获得实际值,就是渲染时实际生效的值

计算值与使用值

计算值是浏览器拿到HTML和CSS后可以立即计算出的值,如font-size的1.2em,可以立即算出来字体大小。

使用值是拿到HTML和CSS后也无法立即计算出的值,如<body>的width为100%,不知道100%是多少像素,需要根据实际用户打开的页面大小获得宽度值,这就是使用值。

可继承属性继承的是父元素的计算值

盒模型

margin、border、padding、content

  • content,默认情况下,width和height是content的,百分数也是相对于content的的值,容器有指定高度时,百分数的height才生效。
  • padding,内边距,设置为百分数时,是相对容器的宽度;设置为多个值时按顺时针排列,上右下左,也可以用padding-top、padding-bottom、padding-left、padding-right设置。
  • border,边框,类型有solid等,具体看下面实践练习例子,可以用border-left-width等灵活设置各个边框的宽度、颜色、类型等。
  • margin,外边距,margin在垂直方向上会合并,称为margin collapse,连续的上下2个元素,实际的垂直方向边距为,上一个元素的margin-bottom和下一个元素margin-top的最大值。

box-sizing计算方式,若值为content-box,则宽高按content的;若值为border-box,则宽高按border的。

overflow,内容超越容器本身大小时,visible:全部展示出来;hidden:隐藏超出的部分;scroll:显示滚动条;auto:自动显示滚动条

布局

常规流(文档流)、浮动、绝对定位

常规流

行级、块级、表格布局、FlexBox、Grid

行级&块级

行级/块级元素与行级/块级盒子是不同的概念

行级盒子并排排列成一行或多行,width和height不适用;块级盒子不和其他盒子并列摆放,适用所有盒模型属性。

行级元素生成行级盒子,内容分散在多个行盒中,有span em strong cite code等

块级元素生成块级盒子,有body artivle div main section h1-6 p ul li等

通过display属性设置block和inline,可以设置任意元素的盒子属性。block块级盒子;inline行级盒子;inline-block本身是行级,可以放在行级盒子中,但可以设置宽高,不会被拆成多行,里面的内容生成了块级盒子;none排版时完全忽略。

回到常规流...

  • 根元素<html>、浮动和绝对定位的元素会脱离常规流
  • 其他元素在常规流内
  • 常规流中的盒子,在某种排版上下文中布局,有行级排版上下文IFC、块级排版上下文BFC、Table排版上下文、Flex排版上下文、Grid排版上下文

行级排版上下文IFC,Inline Formatting Context

只包含行级盒子的容器会创建IFC,排版规则为:

  • 盒子在一行内水平摆放
  • 一行放不下就换行显示
  • text-align决定一行内盒子的水平对齐方式
  • vertical-align决定一个盒子在行内的垂直对齐方式
  • 行级盒子会避开float元素

块级排版上下文BFC,Block Formatting Context

会创建BFC的元素:

  • 根元素<html>
  • 浮动、绝对定位、inline-block
  • Flex子项和Grid子项
  • overflow不是visible的块盒
  • display:flow-root

BFC排版规则:

  • 盒子从上到下摆放
  • 垂直方向margin合并
  • BFC内盒子的margin不会与外面的合并
  • BFC不会和浮动元素重叠

常规流布局内,同一父级下只能全部是行级或块级盒子,如果又有行级又有块级盒子,则会创建匿名的块盒把行级元素包起来,但DOM树里看不到,只有排版的时候会创建。

行级盒子以行为单位,设置border等属性时,每一行都会有,参见实践练习例子。

弹性盒子 Flex Box

display:flex;将元素设置为Flex Box布局,则其子元素均按本元素的Flex Box规则布局,也就是按本元素指定的Flex相关属性的值布局,不再适用IFC和BFC的布局。

一个容器内有多个子元素时,可通过Flex的属性控制子元素的摆放流向、摆放顺序等,Flex可以控制子级盒子的:

  • 摆放流向(上下左右),默认从左到右,而BFC默认是从上到下
  • 摆放顺序
  • 盒子宽高,宽度默认根据内容决定,而BFC默认是100%
  • 水平和垂直方向的对齐
  • 是否允许折行

由于摆放流向不一定是水平或垂直,为明确摆放方向的径向和法向的对齐方式,Flex定义了主轴和侧轴,主轴与摆放方向一致(径向),侧轴与摆放方向垂直(法向)。

主轴上用justify-content规定元素对齐方式,有flex-start flex-end center space-between space-around space-evenly等属性,具体查文档。

侧轴上用align-items规定对齐方式,默认为stretch,有flex-start flex-end center stretch baseline等属性,具体查文档。

可以给其中某个子元素专门设置对齐方式

弹性

子元素上设置子项的弹性,容器有剩余空间就拉伸,空间不够就压缩。

  • flex-grow拉伸能力
  • flex-shink收缩能力
  • flex-basis没有伸展或收缩时的基础长度

Grid布局

display:grid;把(父)元素设置为Grid布局方式,一种二维布局方式,使用块级的Grid布局属性。使用grid-template将容器(父元素)划分网格。

grid-template划分网格:grid-template-columns划分列,grid-template-row划分行,有几个属性值就划分几行(列),属性值可以是auto、具体值或百分数,如grid-template-columns:100px 100px 30% auto;

通过网格线确定区域 image.png 如确定黄线左边的区域

<style>
.a{
    grid-row-start:1;
    grid-column-start:1;
    grid-row-end:3;
    grid-column-end:3;
}
//或者
.a{
    grid-area:1/1/3/3;
}
</style>

浮动

float:left;等属性,目的是实现文字环绕图片等效果,不太用考虑清浮动了,其他场景直接用Flex和Grid。

绝对定位

position属性:

  • static 默认值,非定位元素
  • relative 相对自身原本位置的偏移,不脱离文档流,使用top left bottom right设置偏移长度,刘内其他元素渲染不受影响,认为该元素没有偏移一样布局
  • absolute 绝对定位,脱离常规流,相对于非static祖先元素的定位,其他元素认为该元素不存在,使用top left bottom right设置偏移长度
  • fixed 相对于视口的绝对定位,脱离常规流,使用top left bottom right设置偏移长度
  • sticky 基于用户的滚动位置来定位,粘性定位的元素是依赖于用户的滚动,在 position:relative 与 position:fixed 定位之间切换。当页面再目标区域内时,它的行为就像 position:relative; 而当页面滚动超出目标区域时,它的表现就像 position:fixed;,它会固定在目标位置。

布局存在嵌套关系,一个绝对定位的元素内可能是常规流布局。

三、实践实习例子

CSS选择器

属性选择器

<style>
  input[type="text"]{
  background-color: red;
}
</style>

<form target="">
  <label>
    用户名:
    <input type="text" name="user">
  </label>
  <label>
    密码:
    <input type="password" name="password">
  </label>
</form>

空白符处理

<style>
    #p1{
      white-space: normal;
    }
    #p2{
      white-space: nowrap;
    }
    #p3{
      white-space: pre;
    }
    #p4{
      white-space: pre-wrap;
    }
    #p5{
      white-space: pre-line;
    }
</style>

CSS border类型

<p class="none">无边框。</p>
<p class="dotted">虚线边框。</p>
<p class="dashed">虚线边框。</p>
<p class="solid">实线边框。</p>
<p class="double">双边框。</p>
<p class="groove"> 凹槽边框。</p>
<p class="ridge">垄状边框。</p>
<p class="inset">嵌入边框。</p>
<p class="outset">外凸边框。</p>
<p class="hidden">隐藏边框。</p>
<p class="mix">混合边框</p>

行级盒子的属性

<style>
    span{
      border:2px solid;
    }
</style>
<span>
    您可以通过 border-width 属性为边框指定宽度。
    为边框指定宽度有两种方法:可以指定长度值,比如 2px 或 0.1em(单位为 px, pt, cm, em 等),或者使用 3 个关键字之一,它们分别是 thick 、medium(默认值) 和 thin。
    不难发现,大部分网页的滚动条都是一个样式,并没有很多其他的特别元素。那么如何能让滚动条变的丰富多彩呢?接下来我来手把手教你如何用简单的方式来创造一个有个性的滚动条。
</span>

四、课后个人总结

本节课真的是干货满满,极大丰富了自己的视野,当然也是因为我了解的太少了。本节课对CSS有了由浅入深的理解,从基本的CSS属性,到CSS的布局以及浏览器渲染页面的原理,都有了全新的认识。本节课讲授的众多CSS属性的意义短时间内无法全部记下来,但之后需要不断的练习。以后应该充分利用MDN和W3C CSS规范等文档,学习更多的CSS新特性,也要学会使用浏览器开发者工具,方便调试。

五、参考链接

理解 CSS(上).pdf - 飞书云文档 (feishu.cn)

理解 CSS(下).pdf - 飞书云文档 (feishu.cn)