CSS 指南
本文档用于梳理 CSS 的重难点知识,用于复习巩固, 也用于面试谈经。
CSS 入门
官方文档:developer.mozilla.org/zh-CN/docs/…
CSS 语法
1 CSS 选择器
CSS 选择器:一个标记,用来指定 CSS 规则使用的 HTML 元素。选择器所选择的元素,叫做“选择器的对象”。
1.1 选择器分类
CSS 选择器的类型:
- 基础选择器:标签选择器(elementname)、类选择器(.classname)、ID 选择器(#idname)、属性选择器([attr=value])、通配选择器(*)。
- 组选择器:选择器列表(A, B)
- 关系选择器:兄弟选择器(A ~ B)、邻近兄弟选择器(A + B)、后代选择器(A B)、直接后代选择器(A > B)
- 伪选择器:伪类(:)、伪元素(::)
1.2 选择器重要性
CSS 是层叠样式表,同一个元素可以匹配多个 CSS 规则,如果发生规则冲突,就会按照重要性来选择。
CSS 规则的重要性由以下 3 个因素决定:
- 重要程度:最重要的因素。
- 优先级:排第二的因素。
- 资源排序:排最后的因素。
1.2.1 重要程度
重要程度由以下因素决定:内联样式、!important声明。
内联样式: style 属性内的样式声明。它优先于所有普通的样式,无论其优先级如何。
!important 声明:使用 !important 声明的样式优先于内联样式。示例:
.box {
color: blue !important;
}
注意:内联样式中也可以使用 !important 声明。
1.2.2 优先级
选择器的优先级由三个不同的值(或分量)相加:
- ID:选择器中包含 ID 选择器,则加 100。
- 类:选择器中包含类选择器、属性选择器或者伪类,则加 10。
- 元素:选择器中包含元素、伪元素选择器,则加 1。
选择器的优先级的示例:
| 选择器 | ID | 类 | 元素 | 优先级 |
|---|---|---|---|---|
h1 | 0 | 0 | 1 | 0-0-1 |
h1 + p::first-letter | 0 | 0 | 3 | 0-0-3 |
li > a[href*="en-US"] > .inline-warning | 0 | 2 | 2 | 0-2-2 |
#identifier | 1 | 0 | 0 | 1-0-0 |
button:not(#mainBtn, .cta) | 1 | 0 | 1 | 1-0-1 |
备注: 其他的选择器不会影响优先级。
1.2.3 资源顺序
资源顺序:相同权重的 CSS 规则,会应用最后面的规则。
1.3 CSS 继承
CSS 继承:父元素的某些属性会被子元素继承。比如:color 、font-family 属性。
控制继承:CSS 为属性的继承提供了五个特殊值,用于指导元素如何继承属性。
- inherit:继承父元素的属性值。
- initial:使用该元素的初始值
- revert:使用浏览器的默认值。在许多情况下,此值的作用类似于 unset。
- revert-layer:使用上一个层叠层中建立的值。
- unset:使用自然值。也就是如果属性是自然继承那么就是 inherit,否则和 initial 一样。
2 CSS 级联层
2.1 定义
级联层:显式特异性容器。它将 CSS 规则划分为多个层,然后根据层的顺序来确定 CSS 的重要性。它可以简化 CSS 的重要性:
-
如果不使用级联层,确定重要性需要考虑三个因素:重要程度、优先级、资源排序。其中优先级的计算是最复杂的。
-
如果使用级联层,确定重要性只需考虑二个因素:重要程度、级联层排序。
- 未在级联层中声明的所有 CSS 规则,会被当做最后一个级联层。
- 对于常规(没有
!important声明)的规则冲突,后面的层比前面的重要性高。 - 对于有
!important声明的规则冲突,前面的层比后面的重要性高。
级联源:浏览器默认的级联层。有以下三种:
- 用户代理样式表:浏览器默认的样式。
- 用户样式表:网站访问者在浏览器的配置文件中设置的样式。
- 作者样式表:开发者声明的普通样式。
2.2 创建级联层
创建级联层:使用 @layer 声明。示例:
<style>
/* 创建级联层,并定义其顺序。 */
@layer theme,layout;
/* 默认层:排最后一层。 */
body {
color: #333;
}
/* theme:排第一层 */
@layer theme {
body {
display: grid;
}
}
/* layout:排第二层 */
@layer layout {
body {
display: grid;
}
}
/* 创建的匿名层:排第三层 */
@layer {
body {
margin: 0;
}
}
</style>
引用级联层:使用 @import layer()。示例:
@import url("lib.css") layer(theme);
2.3 级联层的排序
级联层的排序:
| 顺序(从低到高) | 起源 | 重要性 |
|---|---|---|
| 1 | 用户代理 | 正常 |
| 2 | 用户 | 正常 |
| 3 | 自定义级联层 | 正常 |
| 4 | 作者 | 正常 |
| 5 | CSS 动画 | |
| 6 | 作者 | !important |
| 7 | 自定义级联层 | !important |
| 8 | 用户 | !important |
| 9 | 用户代理 | !important |
| 10 | CSS 过渡(正在转换的样式) |
为什么用户代理的 !important 样式重要性最高?
因为用户代理样式表中一般有两类样式:默认样式、规范样式。默认样式可以随便修改;规范样式就是 !important 样式,是一种严格规范,是不能修改的,所以它的重要性最高。
2.4 级联层嵌套
创建嵌套级联层:
@layer theme.layout {
body {
width: 50vw;
}
}
引用嵌套级联层:
@import url("lib.css") layer(theme.layout);
3 CSS @规则
@规则是一些特殊规则,提供 CSS 如何表现的指导。
@import:导入外部样式表。示例:
@import 'styles2.css';
@import 与 link 的区别?
- @import 是 CSS 方式;link 是 HTML 方式
- @import 的样式在 CSS 文件解析之后同步加载;link 的样式加载页面之前异步加载
- @import 只能导入样式表;link 可以通过 ref 指定候选样式
@media:使用媒体查询来应用 CSS。示例:
body {
background: pink;
}
/* 定义视窗宽度大于等于 30em 的样式 */
@media (min-width: 30em) {
body {
background: blue;
}
}
4 CSS 函数
var() 可以插入一个自定义属性(也叫 CSS 变量,是以 -- 开头的属性),比如:
:root {
--main-bg-color: pink;
}
body {
background-color: var(--main-bg-color);
}
attr() 可以获取 HTML 元素的 data-* 属性,比如:
<style>
p:before {
content: attr(data-foo) ' ';
}
</style>
<p data-foo="hello">world</p>
calc() 用于对 CSS 属性值进行计算,比如:
width: calc(100% - 80px);
CSS 属性
CSS 的属性非常多,下面介绍一些重要的属性。
1 布局属性
布局属性用于控制元素的位置。
1.1 布局类型
CSS 的布局类型包含以下几种:
- 定位布局:按照指定坐标的方式摆放元素。
- 浮动布局:按照左右浮动的方式摆放元素。
- 流式布局:按照默认的顺序排列元素。
- 弹性布局:按照伸缩的方式排列元素。
- 多列布局:按照等宽的方式排列元素。
- 网格布局:按照网格的方式排列元素。
- 表格布局:按照表格的方式排列元素。
CSS 的布局行为由以下属性共同决定:
-
position 属性:
- 当值为 absolute、fixed 时,优先级排第一;
- 当值为 relative、sticky 时,优先级排第二;
- 当值为其他时,不影响布局行为。
-
float 属性:优先级排第二
-
display 属性: 优先级排第三。
1.2 定位布局
定位布局:position 属性为非 static 的布局方式。
定位布局会根据指定的位置精确摆放元素,常用于不规则的复杂布局。
position 属性:控制元素的定位方式。可能的值:
-
static:静态定位,按照正常的方式排列元素。
-
relative:相对定位,按照相对于静态定位的位置摆放元素。
-
absolute:绝对定位,按照相对于最近的非 static 定位祖先元素的位置来摆放元素。绝对定位会脱离正常文档流。
-
fixed:固定定位,按照相对于窗口(viewport)的位置来摆放元素。
- 它会脱离正常文档流,并且创建新的层叠上下文。
- 窗口滚动时,它不会移动。
- 当元素祖先的
transform、perspective、filter或backdrop-filter属性非none时,容器由窗口改为该祖先。
-
sticky:粘性定位,按照相对于最先滚动祖先的位置摆放元素。最近滚动祖先滚动时,它不会移动。
在定位布局中,元素的位置由 top、right、bottom、 left 属性决定,元素的层叠优先级由 z-index 属性决定。
1.3 浮动布局
1.3.1 介绍
浮动布局:position 属性为非 absolute、fixed,并且 float 属性为非 none 的布局方式。
浮动布局常用于图片环绕效果。它有以下特点:
- 它会脱离正常文档流;它的盒子区域会与其他盒子重叠,但是内容区域不会重叠。
- 按照 float 属性值的方向,按照代码顺序,先排列浮动(具有 float 属性)元素,再排列非浮动元素。
- 浮动元素默认没有滚动条。
float 属性:控制元素的左右浮动。可能的值:
- none:不进行浮动
- left:元素必须浮动在其所在的块容器左侧
- right:元素必须浮动在其所在的块容器左侧
- inline-start:元素必须浮动在其所在块容器的开始一侧。开始位置由 writing-mode 属性决定。
- inline-end:元素必须浮动在其所在块容器的结束一侧。结束位置由 writing-mode 属性决定。
1.3.2 清除浮动
浮动元素附近的普通元素会环绕在浮动元素周围,为了清除环绕效果(使其在下方展示),需要对其使用 clear 属性。
clear 属性:用来清除受到的浮动影响。可能的值:
- left:停止任何活动的左浮动
- right:停止任何活动的右浮动
- both:停止任何活动的左右浮动
1.3.3 解决溢出问题
当浮动元素高于非浮动元素时,浮动元素会溢出其父元素,因为浮动元素脱离了文档流。为了解决溢出问题,有以下三种方式:
第一种方式:clearfix 小技巧。它先向浮动元素的父元素的最下方插入空白内容,然后将生成的内容清除浮动。示例:
.wrapper::after {
content: "";
clear: both;
display: block;
}
这与在浮动盒子后手动添加诸如 div 的 HTML 元素,并设置其样式为 clear:both 是等效的。
第二种方式:使用 overflow 属性。它将浮动元素的父元素的 overflow 属性设置为除 visible 外的其他值。示例:
.wrapper {
overflow: auto;
}
第三种方式:使用 flow-root 。它将浮动元素的父元素的 dispaly 属性设置为 flow-root 。示例:
.wrapper {
display: flow-root;
}
注意:
- 第三种方式的兼容性不太好,需要检测浏览器是否支持。
- 以上三种方式都是将元素变为 BFC 元素。
2 背景属性
background 属性:定义元素的背景。
2.1 背景简写
background 简写可以包含多个背景内容(包括背景颜色和背景图片),示例:
.bd {
background: url(img/demo.png) center center / 100px 100px no-repeat, red;
}
当 background 属性包多个背景内容时,需要遵循以下规则:
- 多个背景内容之间,需要是逗号隔开。
background-size值只能包含在背景位置之后,并且用 '/' 字符分隔,例如:center / 80%。
2.2 渐变背景
gradient 函数用于设置渐变背景,包含三种类型:
- 线型渐变:linear-gradient(),颜色值沿着一条隐式的直线逐渐过渡。
- 径向渐变:radial-gradient(),颜色值由一个中心点(原点)向外扩散并逐渐过渡到其他颜色值
- 重复渐变:repeating-linear-gradient() 和 repeating-radial-gradient(),重复多次渐变图案直到足够填满指定元素。
下面是一个简单的线型渐变:
<style>
div {
height: 50px;
background: linear-gradient(105deg, red 0%, white 40%, green 80%);
}
</style>
<div />
其中,105 deg 是渐变的方向(按照顺时针方向,0 deg表示正上方),red 0% 是开始位置的颜色。
使用 repeating-linear-gradient 可以实现斑马纹效果,比如:
<style>
div {
width: 200px;
height: 50px;
/* 方向:左上;重复的区间:0 - 5px 为红色,5 - 10 px 为白色 */
background: repeating-linear-gradient(to top left, lightpink, lightpink 5px, white 5px, white 10px);
}
</style>
<div />
使用 repeating-linear-gradient 可以实现水波纹效果,比如:
<style>
div {
width: 200px;
height: 50px;
background: repeating-radial-gradient(powderblue, powderblue 8px, white 8px, white 16px);
}
</style>
<div />
2.3 文字背景
文字背景:使用值为 text 的 background-clip 属性和值为 transparent 的 -webkit-text-fill-color 属性,实现背景图片嵌入文字的效果。示例:
<style>
.clip-text {
background: url(img/demo.png);
background-clip: text;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
</style>
<h1 class="clip-text">文字背景</h1>
注意: 在谷歌浏览器中,需要使用 -webkit-background-clip 属性。
2.4 混合模式
混合模式:将元素的重叠部分混合后,以新的颜色进行展示。混合模式用于文字视频等特效。
2.4.1 定义
混合模式分为两种:
第一种是 background-blend-mode:定义元素的背景颜色、背景图片如何混合。示例:
<style>
.background-multiply {
background-color: red;
background-image: url(img/demo.png);
background-blend-mode: multiply;
}
</style>
<h1 class="background-multiply">混合背景</h1>
第二种是 mix-blend-mode:定义元素的内容和背景与其重叠元素的内容和背景如何混合。示例:
<style>
.normal {
background: red;
}
.mix-multiply {
position: relative;
top: -50px;
background: green;
mix-blend-mode: multiply;
}
</style>
<h1 class="normal">正常元素</h1>
<h1 class="mix-multiply">混合元素</h1>
混合模式的值由 blend-mode 决定,它包含以下几种常用的值:
- normal:最终颜色为顶层颜色。
- multiply:最终颜色为顶层颜色与底层颜色相乘的结果。 如果叠加黑色层,则最终层必为黑色层,叠加白色层不会造成变化。 其效果类似于在透明薄膜上重叠印刷的两个图像。
- screen:最终的颜色是反转顶层颜色和底层颜色,将反转后的两个颜色相乘,再反转相加得到的和得到的结果。 黑色层不会造成变化,白色层导致白色最终层。 其效果类似于(被投影仪)投射到投影屏幕上的两个图像。
2.4.2 文字视频
文字视频:使用值为 screen 的 mix-blend-mode 属性,可以实现视频嵌入文字的效果。示例:
<style>
.box {
position: relative;
/* 设置 font-size 为 0,是为了消除视频下方空隙 */
font-size: 0;
}
.mix-screen {
position: absolute;
top: 0;
height: 100%;
color: black;
font-size: 100px;
font-weight: bold;
background: white;
mix-blend-mode: screen;
}
</style>
<div class="box">
<video src="img/movie.ogv" muted autoplay loop></video>
<div class="mix-screen">文字视频</div>
</div>
3 变换属性
CSS 变换用于在不影响正常文档流的情况下改变元素的位置,支持二维平面和三维空间的旋转、倾斜、缩放、平移。注意: 只能对块级元素进行 CSS 转换。
详细文档:developer.mozilla.org/zh-CN/docs/…
4 动画属性
动画属性分为两种:animation 和 transition。
- animation 属性:按顺序展示 keyframes(关键帧) 中的样式,用于元素创建销毁的场景。详细文档:developer.mozilla.org/zh-CN/docs/…。
- transition 属性:控制元素属性变化的速度,用于元素使用过程(属性变化)的场景。详细文档:developer.mozilla.org/zh-CN/docs/…。
5 编辑属性
编辑属性用于改变元素的形状、模糊等
5.1 裁剪
clip-path 属性:使用裁剪方式创建元素的可显示区域。裁剪用于自定义形状。示例:
.shape {
background: red;
/* 圆形:半径-10px、圆心-盒子中心*/
clip-path: circle(10px at 50% 50%);
}
5.2 滤镜
filter 属性:将模糊或颜色偏移等图形效果应用于元素。滤镜通常用于调整图像、背景和边框的渲染。示例:
.filter {
/* 对输入图像应用阴影效果。 */
filter: drop-shadow(5px 5px 1px rgba(0,0,0,0.7));
}
5.3 遮罩
mask:CSS 属性,根据遮罩元素的透明度来展示被遮挡元素。遮罩常用于切换图标颜色。示例:
.target {
mask: url(#c1) luminance;
}
说明:在谷歌浏览器中,使用 mask 属性引用 svg 时,会有兼容性问题。
CSS 机制
1 盒模型
1.1 定义
CSS 盒模型是指按照盒子的结构描述元素,包含以下部分:
- Content box(内容) : 显示内容的区域,大小由 width 和 height 决定。
- Padding box(内边距) : 包围内容的空白区域;大小由 padding 决定。
- Border box(边框) : 包围内边距的边界。大小由 border 相关决定。
- Margin box(外边距) :包围边框的空白区域。大小由 margin 决定。
CSS 盒模型的类型由 box-sizing 属性决定,分为以下两种:
- content-box:标准盒模型,是 box-sizing 的默认值。标准盒模型中,width 与 height 只包括内容的宽高,不包括边框、内边距。
- border-box:替代盒模型。替代盒模型中,width 与 height 包括内容的宽高、边框、内边距。
1.2 显示类型
盒子的显示类型是指盒子在布局排版时的展示方式,分为两种:
- 外部显示类型:盒子整体的展示方式。
- 内部显示类型:盒子的子元素的展示方式。
盒子的外部显示类型由 display 属性决定,分为以下三种:
-
块级盒子(Block Box)
- 会产生换行
- 会占据父容器在内联方向(行内文本的排列方向)上的所有可用空间。
- width 和 height 属性可以发挥作用。块级盒子默认与父容器等宽。
- 内边距、外边距、边框会推开其他盒子
-
内联盒子(Inline Box)
- 不会产生换行。
- width 和 height 属性将不起作用。
- 垂直方向的内边距、外边距、边框会被应用,但不会把其他处于
inline状态的盒子推开。 - 水平方向的内边距、外边距、边框会被应用,并且会把其他处于
inline状态的盒子推开。
-
内联块盒子(Inline-block Box):可以实现块级盒子的部分效果
- 不会产生换行
- width 和 height 属性可以发挥作用
- 内边距、外边距、边框会推开其他盒子
注意: 行内元素的高度由 font-size 和 父元素的 line-height 决定:
- 第一行的高度:font-size × 1.3125
- 第N行的高度:父元素的 line-height
1.3 外边距重叠
外边距重叠:块级盒子的上外边距和下外边距合并为一个外边距,其大小为单个边距的最大值。
有三种情况会形成外边距重叠:
- 同一层相邻元素之间:A 元素的下外边距和 B 元素的上外边距合并。
- 父元素和后代元素之间没有内容:父元素的上外边距和后代元素的上外边距合并;父元素的下外边距和后代元素的下外边距合并。没有内容是指没有边框、内边距、行内内容。
- 两个元素之间是空的块级元素:A 元素的下外边距和 B 元素的上外边距合并。空的块级元素是指没有边框、内边距、行高内容、高度。
注意: BFC 元素和其子元素不会产生外边距重叠行为。
1.4 滚动条
当元素超出窗口时,默认会在窗口(html 元素的上层)中展示滚动条。
如果希望在指定元素中展示滚动条,需要满足以下条件:
- 元素需要指定高度,并且元素的内容高度大于父元素高度
- overflow 的值为 scroll 或 auto
注意:
- 滚动条出现的位置在盒子的边框内。
- 当元素的内容溢出并且不支持滚动条时,就会在支持滚动条的最近祖先元素中展示滚动条。
2 层叠上下文
z-index 属性:指定层叠上下文中元素的优先级。
当元素满足以下任一条件时,它会形成一个独立的层叠上下文:
- html 元素
- 固定定位或粘性定位的元素。
- z-index 不为 auto 的相对定位或绝对定位元素。
- z-index 不为 auto 的网格布局子元素。
- z-index 不为 auto 的弹性布局子元素。
注意:元素的 z-index 属性只有在层叠上下文中才会生效,如果父元素不是层叠上下文,那么它会找最近的层叠上下文。
3 块格式化上下文
块格式化上下文(Block Formatting Context,BFC)是块级盒子的、能够包含浮动元素的布局区域。
下面的元素会创建块格式化上下文:
- html 元素
- 浮动元素
- 绝对定位或固定定位元素
- 行内块元素(display 值为 inline-block)
格式化上下文会影响盒子布局,会产生以下影响:
- 包含内部浮动:BFC 元素会包含浮动元素。
- 排除外部浮动:BFC 元素不会与浮动元素的盒子区域重叠。
- 阻止外边距重叠:BFC 元素和其子元素不会产生外边距重叠行为。
4 响应式设计
响应式网页设计(responsive web design,RWD):是允许 Web 页面适应不同屏幕宽度因素等,进行布局和外观的调整的一系列实践。
响应式设计由以下技术组成:
- 媒体查询:根据不同的屏幕尺寸设计不同的样式。
- 灵活网格:使用百分比单位指定元素的宽度。
- 响应式图片:根据不同的屏幕选择不同的图片。
- 响应式排版:根据不同的屏幕使用不同的字体大小。
4.1 媒体查询
媒体查询:根据不同的屏幕尺寸设计不同的样式。示例:
/* 当屏幕宽度大于等于 800px 时 */
@media screen and (min-width: 800px) {
.container {
margin: 1em 2em;
}
}
4.2 灵活网格
灵活网格:使用百分比单位指定元素的宽度。比如,元素的宽度是 100px ,父元素的宽度为 1000px ,那么元素的百分比宽度就是 10/1000=10%。
多列布局、网格布局、弹性布局都属于灵活网格的范畴。
4.3 响应式图片
在早期处理图片时,通过 max-width: 100%; 样式,让图片不会溢出,并且保持图片的清晰度。
img {
max-width: 100%;
}
这种方式有两个弊端:
- 小屏手机加载大图时,会浪费宽带
- 无法切换图片。因为在移动端,可能需要换另一张图片,以保证最佳的用户体验。
所以,就有了响应式图片的出现。它通过 picture元素和 img 元素的 srcset 和 sizes 属性,现实不同的屏幕加载不同的图片。详情见响应式图像指南。
4.4 响应式排版
响应式排版:根据不同的屏幕使用不同的字体大小。响应式排版有两种方案:
第一种方案:使用 rem 单位,然后根据媒体查询改变 rem 的大小。示例:
html {
font-size: 16px;
}
h1 {
font-size: 2rem;
}
@media (min-width: 1200px) {
html {
font-size: 24px;
}
}
第二种方案:使用窗口单位 vw。1vw等同于窗口宽度的百分之一。示例:
h1 {
font-size: 6vw;
}
4.5 窗口元标签
移动端浏览器可能默认将窗口宽度设为 960 px,需要使用窗口元标签来指定窗口宽度为设备宽度。比如:
<meta name="viewport" content="width=device-width,initial-scale=1">
CSS 常见问题
1 元素居中
元素居中的通用方法:
第一种,flex,比如:
.container {
display: flex;
align-items: center;
justify-content: center;
}
注意:有多个子元素时,默认水平排列,并且间距为 0。
第二种,grid,比如:
.container {
display: grid;
place-items: center;
}
注意:有多个子元素时,默认垂直排列,并且间距相等(大于 0)。
第三种,margin,比如:
.container {
display: flex;
/* 或者 display: grid; */
}
.box {
margin: auto;
}
注意:在 flex 布局中,有多个子元素时,默认水平排列,并且间距相等(大于 0)。
第四种,transform,比如:
.container {
position: relative;
}
.box {
position: absolute;
top: 50%;
left: 50%;
/* translateX(-50%) 表示沿着 X 轴的反方向平移自身的 50% */
transform: translateX(-50%) translateY(-50%);
}
注意:有多个子元素时,需要单独计算位置。
元素居中的简便方法:
如果是行内元素的水平对齐,可以对父元素使用 text-align: center;;如果是块级元素的水平对齐,可以对子元素使用 margin: auto;
如果是单个元素的垂直居中,可以对父元素使用 line-height: [元素高度];