这是我参与「第四届青训营」笔记创作活动的的第 1天
一、本堂课重点内容:
- 学习什么是 CSS (Cascading Style Sheets)
- 学习如何在页面中使用 CSS
- CSS 在页面中是如何工作的
二、详细知识点介绍:
- CSS 用于定义页面元素的样式(例如字体、颜色、位置和大小等等)
- CSS 的结构由选择器(Selector)、属性(Property)、属性值(Value) 组成,其中属性和属性值组成一个声明(Declaration)
-
在页面中使用 CSS 有三种方式:外链、嵌入和内联
- 推荐优先使用外链:能够使得内容和样式分离
-
<!-- 外链(推荐) --> <link rel="stylesheet" href="/assets/style/style.css"> <!-- 嵌入 --> <style> h1 {margin: 20px;} </style> <!-- 内联 --> <h1 style="margin: 20px">Hello World!</h1>
-
CSS 在页面的工作流程图
选择器(Selector)
- 用于找出页面中的元素并设置样式
-
选择器有五种:通配选择器、标签选择器、ID 选择器、类选择器和属性选择器
- 属性选择器(例如 [disabled] 等) - 匹配含有该属性的元素
- 类选择器(.) - 匹配元素中的 Class 属性
- ID 选择器(#) - 匹配元素中的 ID 属性
- 标签选择器(例如 h1 等) - 匹配含有该标签的元素
- 通配选择器(*) - 匹配页面中的所有元素
子串匹配的属性选择符
| 表达式 | 描述 |
|---|---|
| E[att^="val"] | 匹配具有att属性、且值以val开头的E元素 |
| E[att$="val"] | 匹配具有att属性、且值以val结尾的E元素 |
| E[att*="val"] | 匹配具有att属性、且值中含有val的E元素 |
伪类(Pseudo-classes)
- 伪类常用的有状态伪类和结构性伪类
状态伪类
| 选择器 | 描述 |
|---|---|
| :active | 选择活动的链接。 |
| :focus | 鼠标在元素上聚焦的状态 |
| :link | 未访问的链接 |
| :visited | 已访问的链接 |
| :hover | 鼠标悬停在元素上的状态 |
结构性伪类
| 选择器 | 例子 | 描述 |
|---|---|---|
| :not(selector) | :not(p) | 选择所有 p 以外的元素 |
| :first-child | p:first-child | 选择器匹配属于任意元素的第一个子元素的 元素 |
| :first-of-type | p:first-of-type | 选择的每个 p 元素是其父元素的第一个 p 元素 |
| :last-child | p:last-child | 选择所有 p 元素的最后一个子元素 |
| :last-of-type | p:last-of-type | 选择每个 p 元素是其母元素的最后一个 p 元素 |
| :only-child | p:only-child | 选择所有仅有一个子元素的 p 元素 |
| :nth-child(n) | p:nth-child(2) | 选择所有 p 元素的父元素的第二个子元素 |
| :nth-last-child(n) | p:nth-last-child(2) | 选择所有 p 元素倒数的第二个子元素 |
| :nth-last-of-type(n) | p:nth-last-of-type(2) | 选择所有 p 元素倒数的第二个为 p 的子元素 |
| :nth-of-type(n) | p:nth-of-type(2) | 选择所有 p 元素第二个为 p 的子元素 |
| :only-of-type | p:only-of-type | 选择所有仅有一个子元素为 p 的元素 |
| :target | #news:target | 选择当前活动 #news 元素(点击 URL 包含锚的名字) |
组合(Combinators)
| 名称 | 语法 | 说明 | 例子 |
|---|---|---|---|
| 直接组合 | AB | 满足 A 同时也满足 B | input:focus |
| 后代组合 | A B | 选中 B,如果它是 A 的子孙 | p a |
| 亲子组合 | A > B | 选中 B,如果它是 A 的子元素 | p > em |
| 兄弟选择器 | A ~ B | 选中 B,如果它在 A 后且与 A 同级 | h2 ~ p |
| 相邻选择器 | A + B | 选中 B,如果它紧跟在 A 后 | h2 + p |
-
选择器组
-
body, h1, h2, h3 { margin: 0; }
-
属性 (Property)
颜色(Color)
- 十六进制颜色代码 - #FFFFFF
- RGB - rgb(255, 255, 255)
-
HSL - hsl(18, 91%, 84%)
- Hue(H) - 色相 - 范围 0-360
- Saturation(S) - 饱和度 - 范围 0~100%
- Lightness(L) - 亮度 - 范围 0~100%
-
Alpha
透明度(不透明度) - 范围 0~1 - 越大越不透明- 十六进制颜色代码 - #FFFFFFFF
- RGB - rgba(255, 255, 255, 1)
- HSL - hsl(18, 91%, 84%, 1)
字体(Font)
- 在选择字体时,最好在最后放上一个通用字体族,以来保证字体的正常显示。
-
当想要为不同语言设置不同字体时,应将部分的放在前面,例如下面为英文设置英文字体
-
body { font-family: Helvetica, Microsoft YaHei, sans-setif; } - 当遇到英文时则使用 Helvetica ,当遇到中文时由于 Helvetica 字体无中文字体,因此则跳转到下一个使用 Microsoft YaHei ,若遇到 Microsoft YaHei 也没有包含的字体时,则会跳转到通用字体族 sans-setif
-
属性值(Value)
- 在 CSS 中,每个属性一个初始值
- 可以使用 initial 关键字显式重置为初始值
特异度(Specificity)
当我们编写 CSS 的时候,有时候会因自己的疏忽导致同一元素下重复,例如下面的代码
<div>
<h1 class="title">Title</h1>
</div>
<style>
.title {
color: #000000;
}
div h1 {
color: #ffffff;
}
</style>
那么这时候 CSS 的优先级则是根据该选择器的特异度来判断的
组成
特异度的分数由 ID(#)、(伪)类(.)、标签(E) 三部分组成,这三部分分别对应着百位、十位和个位,让我们来举个例子:
-
#nav .list li a:link
- ID - 1 - #nav
- (伪)类 - 2 - .list & :link
- 标签 - 2 - li & a
继承(Inherit)
某些属性会自动继承其父元素的计算值,除非显式指定一个值,那么如何简单的进行显式继承呢,来看看下面的例子吧
* {
box-sizing: inherit;
}
取值过程
- DOM 树 和 样式规则 传入 filtering
- filtering(通过选择器匹配、属性有效和符合当前 media 等条件进行过滤)
- 过滤后可能会有多个声明值(Declared Values),例如 p {font-size: 16px} 和 p.next {font-size: 2em}
- 在层叠过程中,将声明值传入 cascading 通过来源、!important、特异度、书写顺序等条件筛选出优先级最高的一个属性值则为层叠值(Cascaded Value)
- 将层叠值放入 defaulting 中,当层叠值为空的时候则使用继承或者初始值,经过前面的处理后将获得一个指定值(Specified Value),由于 CSS 的每个属性都有自己的初始值,所以一定不为空
-
将指定值放入 resolving 中,将指定值中的一些相对值或者关键字转换为绝对值,例如将 em 转换为 px ,相对路径转换为绝对路径等等,转换后则为计算值(Computed Value)
在 resolving 中相对值的转换仅针对能从 CSS 直接分析出来的,例如父级为 20px,则当子级为 2em 时则转换后则为(20 * 2)40px
- 将计算值放入 formatting 中,对计算值进行进一步的转换,将关键字和百分比转换为绝对值,此时的转换是从实际布局出手进行转换,转换后则为使用值(Userd Value)
- 将使用值放入 constraining 中,将小数像素值转换为整数后得到最后的实际值
布局(Layout)
- 布局用于确定内容大小和位置的算法
-
相关技术
- 常规流(行级、块级、表格布局、FlexBox、Grid布局)
- 浮动
- 绝对定位
相关属性
width
- 指定 content box 宽度
- 取值可以为长度、百分数、auto
- 百分数相对于容器的 content box 宽度
height
- 指定 content box 高度
- 取值可以为长度、百分数、auto
-
百分数相对于容器的 content box 宽度
- 只有容器有指定的高度时,百分数才可以生效
padding
- 指定元素四个方向的内边框
-
三种写法
- padding: 10px; - 上下左右内边框均为 10px
- padding: 10px 20px; - 上下边框为 10px,左右边框为 20px
- padding: 10px 20px 10px 20px; - 四个数值分别对应上右下左 (顺时针)
margin
- 指定元素四个方向的外边框
- 当上容器的下外边框为 100px ,下容器的上外边框为 100px 时,只会显示 100px 而不是 200px
border
- 指定元素四个方向的边框
- 拥有三个属性:border-width、border-style、border-color
-
可以通过设置不同方向的边框画出三角形
-
#triangle { width: 0; height: 0; border-width: 30px; border-style: solid; border-color: transparent transparent black; }
-
块级(display: block)
- 不和其他盒子并列摆放
- 适用所有的盒模型属性
- 常见标签:body、article、div、main、section 等
BFC(Block Fomatting Context)
-
形成 BFC 的条件
- 根元素(body)
- 浮动(float)、绝对定位(position)
- display 属性为 inline-block,table-cell,table-caption,flex
- overflow 属性不为 visible
-
BFC 的排版规则
- 盒子从上到下摆放
- 垂直 margin 合并
- BFC 内盒子的 margin 不会和外部的合并
- BFC 不会和浮动元素重叠
- BFC 可以看似成隔离的独立容器,容器里面的子元素不会影响到外面的元素,反之亦然
行级(display: inline)
- 和其他行盒子一起放在一行或者拆开成多行
- 盒模型中的 width 和 height 属性无效
- 常见标签:span、em、strong、code 等
IFC(Inline Formatting Context)
- 只包含行级盒子的容器会创建一个 IFC
-
IFC 的排版规则
- 盒子在一行内水平摆放,一行放不下则换行
- Text-align 属性决定一行内盒子的水平对齐
- Vertical-align 属性决定一行内盒子的垂直对齐
- 会自动避开浮动(float)元素
Flex Box(display: flex)
- Flex 能够控制子盒子的摆放的流向(默认从左至右)、顺序、宽度和高度、水平和垂直方向对齐、是否允许拆行等
- 经过 Flex Box 的中心点的水平线为主轴,垂直线为侧轴
flex-grow
- 用于设置有剩余空间时的伸展能力
-
例如 Flex Box 容器的宽度为 300px ,但实际内容使用仅占 200px,则会根据 flex-grow 所设置的值进行剩余空间的分发
-
<div class="index"> <div class="a"></a> <div class="b"></a> </div> <style> .index { display: flex; width: 300px; } .a, .b { width: 100px; } .a { flex-grow: 2; } .b { flex-grow: 1; } </style> - 此时由于 a 的伸展能力为 2 ,b 伸展能力为 1 ,因此剩余的 100px 将以 2:1 的比例分别给 a 和 b
-
flex-shrink
- 用于设置容器空间不足时的收缩能力
- 实际的使用和上述的 flex-grow 相似,因此例子就略过了(
Grid 布局(display: grid)
- 使用 grid-template 相关属性将容器划分为网络
网络轨道
我们可以通过设置 grid-template-columns 和 grid-template-rows 属性来定义网格中的行和列
例如
- grid-template-columns: 100px 100px 100px (表示三列)
- grid-template-rows: 100px 100px 100px 100px(表示四行)
网格线
N 行有 N+1 条水平网格线,M 列有 M+1 条垂直网格线
可以通过设置 grid-row-gap 和 grid-columns-gap 设置行间隙和列间隙
Flex Box 和 Grid 布局区别
Flex Box 布局可以看成是一维排版
Grid 布局可以看成是二维排版