1. 基础知识
1.1 层叠(Cascading)、优先级
1.1.1 层叠三大规则
-
样式表来源
-
用户代理样式 浏览器默认样式
-
用户样式表 很少有
-
作者样式表 developer写的
-
作者样式表中的
!important -
用户样式表中的
!important -
用户代理样式表中的
!important重要程度递增
-
-
选择器优先级
-
基础选择器
-
组合器
- 子组合器
- 相邻兄弟组合器
- 通用兄弟组合器
- 复合选择器
-
属性选择器
-
伪类选择器
-
伪元素选择器
-
逻辑选择器
选择器优先级
内联(o) > id(a) > class = attribute = pseudo-class(b) > type = pseudo-element(c)
a b c 标记(a,b,c) ul li.red0 1 2 (0,1,2) #container:hover1 1 0 (1,1,0) 通用选择器 0 0 0 (0,0,0) div :is(p, #card)1 0 1 (1,0,1) - 内联样式不属于选择器,为方便比较记忆,放在这里做对比
:is() :not() :has()本身不计入优先级,以参数中最高的优先级为准,:where()优先级为 0
-
-
源码位置
- 对于
@inport的样式,根据@inport的顺序 - 对于 link 和 style 标签的样式,根据在 document 中的顺序决定
- 对于
由层叠概念引出的 CSS 代码 good practice
- 选择器尽量少用 id
- 尽量不要用
!important - 自己的样式加载在引用库样式的后面
1.2 继承
-
大部分具有继承特性的属性根文本相关:
color font font-family font-size font-weight font-variant font-style line-height letter-spacing text-align text-indent text-transform white-space word-spacing
-
还有少部分列表、表格的属性可以使用 inherit 关键字显示指定一个属性值从其父元素继承
1.3 CSS 的值和单位
值
- 文字类:比如像 initial 的关键字,颜色、位置等
- 数值类:比如 z-index:1 这种数值,或者带有单位的数值、百分比等
- 函数生成:比如
calc(),min(),max()等
单位
-
长度
- 绝对长度:px, pt, cm, in...
- 相对长度:em, rem, ex, rex... vw, vh, vmin, vmax...
-
角度:deg, grad, turn, rad
-
时间:s, ms
-
分辨率:dpi, dpcm, dppx
1.4 盒模型
浏览器根据视觉格式化模型(visual formatting model),将所有元素表示为盒子模型,CSS 通过盒模型做 layout。
-
控制盒子类型
display: block、inline、inline-block、flex...
-
控制盒子大小 & 计算方式
width,height...
box-sizing: content-box、border-box
-
控制盒中内容流
overflow: auto、scroll、hidden...
-
控制定位
-
position: static、relative、absolute、fixed、sticky
-
是否可见
-
visibility: visible、hidden...
实现三角形
<div class="triangle-bottom"></div>
.triangle-bottom {
width: 0;
height: 0;
border-left: 50px solid transparent;
border-right: 50px soild transparent;
border-bottom: 50px soild red;
}
实现水平居中
<div class="wrap">
<div class="h-center"></div>
</div>
.wrap {
width: 100%;
height: 80px;
border: 1px dashed grey;
}
.h-center {
width: 100px;
height: 50px;
background-color: navajowhite;
// 左右两侧的 margin 使用 auto 将水平方向剩余空间均分 auto
margin: 10px auto;
}
1.4.1 负外边框
padding、border、margin 中,只有 margin 可以设置负值。
- 设置左边或顶部的负外边距,元素就会相应地向左或向上移动,导致元素与它前面的元素重叠
- 如果设置右边或者底部的负外边距,并不会移动元素,而是1将它后面的元素拉过来
2. 布局和定位
CSS 3 之前的常用布局
-
Normal Flow 常规流
- 默认的布局方式
- 有块级格式化上下文和内联格式化上下文
-
Float 浮动流
- 用 float 属性控制
- 脱流,做横向布局
-
Positioning 定位流
- 用 position 属性控制
- fixed 和 absolute 脱离文档流可以自由定位、覆盖等
CSS 3 之后的新增布局
- Flex 弹性盒子布局
- Grid 网格布局
- Multicol 多列布局
- 一维空间布局
- 二维空间布局
- 文本、内容的多列展示
2.1 常规流布局
2.1.1 块级格式化上下文(block formatting context)
格式化上下文的布局规范
在一个块格式区域中,盒子会从包含块的顶部开始,按序垂直排列。同级盒子间的垂直距离会由“margin”属性决定。相邻两个块级盒子之间的垂直间距会遵循外边距折叠原则被折叠。
在一个块格式区域中,每个盒子的左外边缘会与包含块左边缘重合(如果是从右到左的排版顺序,则盒子的右外边缘与包含块右边缘重合)。
块格式化上下文(Block Formatting Context,BFC)是 Web 页面的可视 CSS 渲染的一部分,是块级盒子的布局过程发生的区域,也是浮动元素与其他元素交互的区域。
如何触发一个盒子的 BFC 特性
- display: flow-root | inline-block
- position: absolute | fixed
- float: 不为 none
- overflow: 不为 visible
2.1.2 外边距塌陷
会产生外边距塌陷的情况
- 两个兄弟元素之间相邻的上下外边距
- 父子元素之间相邻的上下外边距
- 内容为空元素自己相邻的上下外边距
消除外边距塌陷的方法
- 在两个相邻的上下边距之间增加 border、padding 或内联元素,使之不相邻
- 在父子元素重叠时,还可以设置父元素为 BFC,使得父子不在同级 BFC 中
2.1.3 内联级格式化上下文
在内联格式区域中,盒子会从包含块的顶部开始,按序水平排列。只有水平外边距、边框和内边距会被保留。这些盒子可以以不同的方式在垂直方向上对齐:可以底部对齐或顶部对其,或者按文字底部进行对齐。我们把包含一串盒子的矩形区域称为一个线条框。(The rectangular area that contains the boxes that form a line is called a line box.)
-
单行文字垂直居中,比如标题
利用了 line-height 的垂直居中的特性
<div class="title">我是标题</div>.title { background: antiquewhite; font-size: 18px; line-height: 36px; height: 36px; } -
文字和 icon 垂直对齐
利用了 line box 中计算高度的原理和 vertical-align 的设置,垂直对齐,但不是完全垂直居中
如果设置父元素 font-size:0,基线和中线重叠,则居中对齐
<div class="wrap"> <img class="image" src="dy.png"> <span class="text">抖音同款能力</span> </div>.image { width: 24px; height: 24px; vertical-align: middle; } .text { font-size: 16px; line-height: 32px; margin-left: 4px; vertical-align: middle; }
2.2 弹性盒子布局
Flexible Box Layout 是为了提供更加高效灵活的布局方式,在即便是宽高未知的情况下,也能排列和分割一个盒子内部的布局。而且在不同布局方向(横向/纵向)的调整更为灵活。
弹性盒子的相关属性
-
作用于父元素(flex container):
-
建立一个弹性盒子
display: fex | inline-flex;
-
规定盒子的主轴方向
flex-direction: row | column |...;
-
子元素折行显示形式
flex-wrap: nowrap | wrap |wrap-reverse;
-
主轴方向子元素的排列方式
justify-content: center | space-betweenI...;
-
交叉轴方向子元素的对齐方式
align-items: flex-start | center | stretch1...;
-
交叉轴方向多行子元素的布局方式
align-content: flex-start | space-between1...;
-
以明确值设定子元素间的间隔
gap:
<row-gap><column-gap>
-
-
作用于子元素(flex items):
-
规定 item 未放缩之前的默认大小
flex-basis: auto | 长度值...;
-
规定有剩余空间时,对 item 的分配比例
flex-grow: number;
-
规定空间不够时,对 item 的压缩的比例
flex-shrink: number;
-
以上三项的缩写
flex: grow shrink basis; 默认 0 1 auto
-
规定 item 从左到右(row 布局)显示的顺序
order: number; 默认是0
-
规定单个 item 在交叉轴上的位置
align-self: auto | center | flex-start...
-
实例
<div class="filename">
<span class="filename__base">
this-file-has-a-really-really-long-filename.
</span>
<span class="filename__extension">
pdf
</span>
</div>
.filename {
display: flex;
}
.filename__base {
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
.filename__extension {
flex-shrink: 0;
}
2.3 网格布局
Grid 网格布局是一个基于栅格的二维布局系统,旨在彻底改变基于网格用户界面的设计。
CSS 网格布局擅长于将一个页面划分为几个主要区域,以及定义这些区域的大小、位置、层次等关系(前提是 HTML 生成了这些区域)。
像表格一样,网格布局让我们能够按行或列来对齐元素。然而在布局上,网格比表格更可能做到或更简单。例如,网格容器的子元素可以自己定位,以便它们像 CSS 定位的元素一样,真正的有重叠和层次。
-
作用于父元素:
-
display: grid | inline-grid;
-
用来生成显式的列、行
grid-template-colums/rows: 数值/百分比/fr/repeat()等;
-
规定区域(area)的分布
grid-tempate-areas: "header header" "sidebar content" "footer footer";
-
规定默认的排序方向
grid-auto-flow: row (dense) | column (dense);
-
其他属性
-
-
作用于子元素:
-
规定占用的列、行
grid-colum/row:
<start-line>/<end-line>;是 grid-colum/row-start 和 grid-colum/row-end 的缩写形式
-
规定占用的 area
grid-area: header;
-
将面设置为均分的 3*3grid 布局
.face {
display: grid;
gird-template-rows: repeat(3, 1fr);
gird-template-columns: repeat(3, 1fr);
gird-template-areas:
"lt . rt"
"lc cc rc"
"lb . rb";
}
规定好所需要的点占用的 area
.lt-dot {
gird-area: lt;
}
.rt-dot {
gird-area: rt;
}
.lc-dot {
gird-area: lc;
}
.cc-dot {
gird-area: cc;
}
.rc-dot {
gird-area: rc;
}
.lb-dot {
gird-area: lb;
}
.rb-dot {
gird-area: rb;
}
Grid 和 Flex 布局的使用策略
-
Flex
- 一维布局
- 基于内容
- 浏览器兼容性更好
-
Grid
- 二维布局
- 基于布局
- 2017年后浏览器的版本普遍支持
-
Grid for layout, Flexbox for components
- 大面积或整体布局推荐使用 Grid 布局
- 小面积或组件中,或 Grid Item 中可以使用 FLex 做灵活布局
2.4 定位 position
为了我们可以在文档流的基础上,让元素移动,做出更多灵活的改变。当 position 属性的取值非 static 时,可以使用 top,right,bottom,left 对其进行定位。
-
relative
元素相对于自己原来在文档流中的位置进行定位,但是原来文档流的空间还在。
```
.relatived {
position: relative;
top: 30px;
left: 10px;
}
```
-
absolute
元素被移出正常文档流,且没有预留空间,相对于最近的非 static 定位祖先元素的进行定位。
```
.wrap {
position: relative;
}
.absoluted {
position: absolute;
top: 30px;
left: 10px;
}
```
-
fixed
元素被移出正常文档流,且没有预留空间,相对于屏幕视口进行定位,屏幕滚动也不会改变位置。
.fixed-pos { position: fixed; top: 10%; left: 10%; } -
sticky
元素相对它的最近滚动祖先(祖先的 overflow 是 scroll/hidden/auto)的视口(scrollport)定位。
.sticky { position: sticky; top: 20px; }
3. 层叠上下文(The Stacking Context)
层叠上下文是对 HTML 元素的三维构想,将元素沿着垂直屏幕的虚构的 Z 轴排开。
- 层叠上下文可以包含在其他层叠上下文中,并且一起创建一个层叠上下文的层级。
- 每个层叠上下文都完全独立于它的兄弟元素:当处理层叠时只考虑子元素。
- 每个层叠上下文都是自包含的:当一个元素的内容发生层叠后,该元素将被作为整体在父级层叠上下文中按顺序进行层叠。
文档中的层叠上下文由满足以下任意一个条件的元素形成:
-
文档根元素(
<html>); -
position 值为 absolute(绝对定位)或 relative(相对定位)且 z-index 值不为 auto 的元素;
-
position 值为 fixed(固定定位)或 sticky(粘滞定位)的元素(沾滞定位适配所有移动设备上的浏览器,但老的桌面浏览器不支持);
-
flex 容器的子元素,且 z-index 值不为 auto;
-
grid 容器的子元素,且 z-index 值不为 auto;
-
opacity 属性值小于 1 的元素;
-
mix-blend-mode 属性值不为 normal 的元素;
-
以下任意属性值不为 none 的元素:
- transform
- filter
- backdrop-filter
- perspective
- clip-path
- mask / mask-image / mask-border
-
isolation 属性值为 isolate 的元素;
-
will-change 值设定了任一属性而该属性在 non-initial 值时会创建层叠上下文的元素;
-
contain 属性值为 layout、paint 或包含它们其中之一的合成值(比如 contain: strict、contain: content)的元素。
层叠顺序不仅指不同的层叠上下文的顺序,同一个层叠上下文内,元素间也有顺序
编写 z-index 的建议
- 使用 CSS 变量或者预处理语言的变量,管理 z-index 的值
- 将预设间隔设置为 10 或 100,方便后续的插入
4. 变形、过度、动画
4.1 transform 变形
2D 相关属性:
- transform:translate(移动)、rotate(旋转)、scale(放缩)、matrix(变形矩阵)等
- transform-origin:right top、center 等表示变形时依据的原点
4.1.1 3D
3D相关属性:
- transform: translate3d、rotates3d、scale3d、matrix3d 等
- transform-origin: right top、50px 30px 等表示变形时依据的原点
- transform-style: flat 或 preserve-3d 看子元素的 3d 表现
- perspective: 观看点距离 z=0 这个平面的距离,可以在 transform 中用 perspective() 使用作用为当前元素,也可以直接使用,给后代元素一个统一值
- perspective-origin: 观看者的位置,如 top、bottom 等
- backface-visibility: 元素正面只有朝向观察者的时候可见
4.2 transition 过渡
通过指定某些元素属性从一种起始状态,在一段时间内以某种变化节奏,过渡到终止状态。
div {
transition: <property> <duration> <timing-function> <delay>;
}
其中 timing-function 一般有三种用法:线性、贝塞尔曲线、阶跃.
4.3 anmiation 动画
CSS animations 使得可以将从一个 CSS 样式配置转换到另一个 CSS 样式配置。动画包括两个部分:描述动画的样式规则和用于指定动画开始、结束以及中间点样式的关键帧。
@keyframes关键帧用来定义动画过程中出现1的关键样式
animation-*的子属性有:
-
animation-delay设置延时,即从元素加载完成之后到动画序列开始执行的这段时间。
-
animation-direction设置动画在每次运行完后是反向运行还是重新回到开始位置重复运行。
-
animation-duration设置动画一个周期的时长。
-
animation-iteration-count设置动画重复次数,可以指定 infinite 无限次重复动画
-
animation-name指定由
@keyframes描述的关键帧名称。 -
animation-play-state允许暂停和恢复动画。
-
animation-timing-function设置动画速度,即通过建立加速度曲线,设置动画在关键帧之间是如何变化。
-
animation-fill-mode指定动画执行前后如何为目标元素应用样式。
5. 响应式设计
响应式设计推荐遵循的原则
- 优先选用流式布局,如百分比、flex、grid 等
- 使用响应式图片,匹配尺寸,节省带宽
- 使用媒体查询为不同的设备类型做适配
- 给移动设备设置简单、统一的接口
- 使用相对长度,em、rem、vm 作为长度度量
5.1 媒体查询的使用
媒体查询允许某些样式只在页面满足特定条件时才生效。我们可以将媒体类型(如 screen、prit)以及媒体特性(如视口宽度、屏幕比例、设备方向:横向或纵向)做为约束条件。
使用媒体查询的一些Tips
- 媒体查询同样遵循 cascading 层叠覆盖原则,min- 和 max- 选择一个
- 由于设备的多样化逐渐不可枚举,断点的选择尽量根据内容选择
- 由于断点的增加会增加样式处理的复杂度,所以尽量减少断点
5.2 设备像素、参考像素和移动设备视口
5.2.1 设备像素
设备像素(device pixels),又称为物理像素。指设备能控制显示的最小物理单位,不一定是一个小正方形区块,也没有标准的宽高,只是用于显示丰富色彩的一个“点”而已。
5.2.2 DPI & PPI
DPI:(Dots Per Inch,每英寸点数),图像每英寸(1 英寸 = 25.4 毫米)长度内的像素点数。我们可以把像素理解为小方块,dpi 就可以理解为一英寸长度内排列的像素数。通过图像的 dpi 我们就可以计算出在这个图像中像素的边长,如果也知道图像的分辨率(宽高像素数),就可以知道该图像的真实尺寸。
PPI:( pixels per inch,每英寸多少像素数), 更确切的说法应该是像素密度,也就是衡量单位物理面积内拥有像素值的情况。我们知道,ppi 越高,每英寸像素点越多,图像越清晰。
5.2.3 CSS 像素
CSS 像素——在 CSS 中以 px 为后缀——是一个长度单位,大致相当于一个肉眼可以轻松看到的小点的长宽,否则就是尽可能小的长度。根据定义,一个 CSS 像素应当看起来是在距离观察者一臂之遥且像素密度为 96 DPI 的屏幕中的一个物理像素。
5.2.4 DPR 设备像素比
设备像素比(Device Pixel Ratio, DPR):其实指的是 window.devicePixelRatio, 被所有 WebKit 浏览器以及 Opera 所支持,一个设备的物理像素与逻辑像素之比。
5.2.5 移动端的 viewport
视口代表当前可见的计算机图形区域。在 Web 浏览器术语中,通常与浏览器窗口相同,但不包括浏览器的 UI,菜单栏等——即指你正在浏览的文档的那一部分。一篇文档,比如这篇文章,可能会非常长。你的视口就是你现在所能见到的所有事物。值得注意的是“什么是视口区域”这个问题,页面中的一些导航菜单也包括在其中。视口的大小取决于屏幕的大小,无论浏览器是否处于全屏模式,是否被用户缩放了。视口外的区域,比如这个文档的参见部分,可能需要滚动到其所在的区域才会出现在屏幕上。
- 在尺寸较大的设备中,在这些设备上,应用显示区域不一定是全屏的,视口是浏览器窗口的大小。
- 在大多数移动设备中,浏览器是全屏的,视口是整个屏幕的大小。
- 在全屏模式下,视口是设备屏幕的范围,窗口是浏览器窗口,浏览器窗口大小小于或等于视口的大小,并且文档是这个网站,文档的大小可比视口长或宽。
5.3 相对长度的使用
5.3.1 em
相对长度单位,这个单位表示元素的 font-size的计算值。如果用在font-size属性本身,它则表示元素继承的 font-size 值。
5.3.2 rem
这个单位代表根元素(通常为<html>元素)的 font-size大小。当用在根元素的 font-size上面时,它代表了它的初始值。
5.3.3 vw 和 vh
- vw:视口的初始包含块的宽度的 1%。
- vh:视口的初始包含块的高度的 1%。