CSS布局与动效知识梳理
概述
本文将布局和动效中使用频率最高的知识点串成一条线:定位处理层叠与脱离文档流,Grid 处理二维复杂布局,多列处理文本流排版,2D/3D 变换处理视觉变形,过渡与动画处理时间维度的状态切换。
一、定位布局
定位的核心价值:控制元素脱离正常流、层叠顺序以及相对于谁定位。
position:定位模式
css
/* position: static | relative | absolute | fixed | sticky */
static:默认值,元素在正常文档流中,top/left等偏移属性无效。relative:相对于元素自身原位置 偏移,仍占据原空间,不影响其他元素布局。常用于为子元素创建定位参照。absolute:脱离文档流,相对于最近的定位祖先 (非static的父级)定位。若无,则相对于<body>。日常写 absolute 时务必在父级设position: relative。fixed:脱离文档流,相对于浏览器视口定位,滚动不改变位置。用于固定导航栏、悬浮按钮、弹窗遮罩。sticky:滚动到达阈值前为relative,到达后切换为fixed。典型场景是吸顶导航。
css
.nav {
position: sticky;
top: 0; /* 滚动到顶部时吸附 */
z-index: 10;
}
注意:sticky 的父级不能设 overflow: hidden,否则会退化为 relative。
偏移属性
top / right / bottom / left 仅对 position 非 static 的元素生效。百分比值相对于包含块的对应维度计算。
z-index 与层叠上下文
z-index 控制定位元素在 Z 轴上的堆叠顺序,值越大越靠前。仅对定位元素(非 static)生效。
新层叠上下文的触发条件(除 position 非 static + z-index 非 auto 外,高频触发项):opacity < 1、transform 非 none、filter 非 none。一旦触发,子元素的 z-index 仅在当前上下文中比较,不会跨上下文穿透。
区分:z-index: 9999 不一定最高------如果它所在的层叠上下文整体低于另一个层叠上下文,再大也无效。
常见模式
绝对定位居中(宽高已知):
css
.box {
position: absolute;
top: 50%; left: 50%;
width: 400px; height: 300px;
margin-left: -200px; /* 负宽度一半 */
margin-top: -150px; /* 负高度一半 */
}
遮罩层 + 弹窗:
css
.overlay { position: fixed; inset: 0; background: rgba(0,0,0,.5); z-index: 99; }
.modal { position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); z-index: 100; }
inset 是 top/right/bottom/left 的四合一简写,inset: 0 即铺满包含块。
二、网格布局
Grid 是 CSS 首个真正的二维布局方案,同时控制行和列。与 Flex(一维)互补。
grid-template-columns / grid-template-rows:轨道定义
定义网格的列宽和行高。三个核心工具:fr 单位、repeat() 函数、minmax() 函数。
css
.container {
display: grid;
grid-template-columns: 1fr 2fr 1fr; /* 三列,中间列占一半 */
grid-template-columns: repeat(4, 1fr); /* 四等分 */
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); /* 响应式核心 */
grid-template-rows: auto 1fr auto; /* 经典 header-content-footer */
}
fr:弹性单位,按比例分配剩余空间,类似 Flex 的flex-grow。repeat(次数, 轨宽):减少重复书写。minmax(min, max):轨道最小/最大尺寸约束,配合auto-fill实现无断点换行。
gap:轨道间距
css
.container {
gap: 20px; /* 行和列间距统一 */
gap: 20px 16px; /* 行间距 20px,列间距 16px */
}
替代传统 margin 方案,间距仅作用在轨道之间,容器边缘无多余空隙。
grid-auto-rows / grid-auto-flow:隐式网格
显式网格是 grid-template-* 定义的轨道,超出部分由隐式网格接管。
css
.container {
grid-auto-rows: 200px; /* 隐式行高 */
grid-auto-flow: dense; /* 紧密填充,不留空洞 */
}
dense 适合图片瀑布流,但会改变元素视觉顺序,注意无障碍影响。
grid-column / grid-row:项目跨轨
css
.item {
grid-column: 1 / 3; /* 从第 1 条线跨到第 3 条线 = 占 2 列 */
grid-column: span 2; /* 跨 2 列,等价写法 */
grid-row: 1 / -1; /* -1 表示最后一条线,占满全部行 */
}
网格线从 1 开始编号,负值从末尾倒数。
grid-template-areas:命名布局
给网格区域命名,直观表达页面结构。
css
.container {
grid-template-areas:
"header header header"
"sidebar content content"
"footer footer footer";
grid-template-columns: 200px 1fr 1fr;
grid-template-rows: auto 1fr auto;
}
.header { grid-area: header; }
.sidebar { grid-area: sidebar; }
.content { grid-area: content; }
.footer { grid-area: footer; }
区域必须组成矩形,不规则形状无效。
对齐属性
place-items:控制项目在各自单元格内的对齐(align-items+justify-items简写)。place-content:控制整个网格在容器内的对齐(align-content+justify-content简写)。
css
.container {
place-items: center; /* 每个单元格内居中 */
place-content: center; /* 整个网格在容器内居中 */
}
auto-fill 和 auto-fit
两者的差异仅在空间有剩余时体现:
auto-fill:保留空轨道占位,空间有多余时留白。auto-fit:折叠空轨道,已有项目拉伸填满。
css
/* 两者在内容溢出时行为一致,差异在内容不足时 */
.container { grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); }
/* 一行只放 3 个卡片时:auto-fill 右边留白,auto-fit 卡片拉伸填满 */
三、多列布局
多列布局专为文本流设计,让长文自动分列,类似报纸排版。与 Grid 不同,它不创建二维网格,而是让内容像水流一样自动灌入各列。
column-count / column-width
css
.container {
column-count: 3; /* 固定列数 */
column-width: 250px; /* 固定列宽,列数由容器宽度自动计算 */
columns: 3 250px; /* 简写:列数 + 列宽 */
}
column-width 与 column-count 同时设置时,以 column-count 为最大列数上限。
column-gap / column-rule
css
.container {
column-gap: 30px; /* 列间距 */
column-rule: 1px solid #ddd; /* 列间分隔线,语法同 border */
}
column-rule 不占空间,仅视觉分割。
column-span: all
让某个子元素跨越多列,常用于文章中的小标题。
css
h2 { column-span: all; }
注意:Firefox 早期不支持,现在已全面可用。
break-inside: avoid
防止元素在多列中断裂,保证卡片、图片等整体在一列内。
css
.card {
break-inside: avoid; /* 避免内容被拆分到不同列 */
}
适用场景
长文排版(博客正文、帮助文档)用多列可提升阅读体验;卡片列表用 Grid,不建议用多列------多列的列高不可控,且项目顺序是"从上到下再从左到右",不符合大多数 UI 的阅读习惯。
四、2D/3D 变换
transform 在元素渲染的最后阶段生效,不影响文档流 ------元素变形后原位置仍被占据,类似 position: relative 的占位行为。
2D 变换核心函数
css
.element {
transform: translate(20px, 10px); /* 平移:右移 20px,下移 10px */
transform: translateX(20px); /* 仅水平平移 */
transform: translateY(-10px); /* 仅垂直平移(负值向上) */
transform: rotate(45deg); /* 旋转 45 度 */
transform: scale(1.2); /* 缩放 1.2 倍 */
transform: scale(1.2, 0.8); /* 水平 1.2,垂直 0.8 */
transform: skew(10deg, 5deg); /* 倾斜 */
}
translate 的百分比相对于元素自身尺寸 ------这是用 translate(-50%, -50%) 实现绝对定位居中的原理。
transform-origin:变换原点
默认原点在元素中心 (50% 50%)。旋转和缩放围绕此点进行。
css
.element { transform-origin: top left; } /* 原点在左上角 */
.element { transform-origin: 0 100%; } /* 原点在左下角 */
3D 变换
三个前置条件:① 父级设 perspective 提供景深,② 父级设 transform-style: preserve-3d 保持 3D 空间,③ 必要时 backface-visibility: hidden 隐藏背面。
css
.scene {
perspective: 800px; /* 景深,值越小 3D 效果越强烈 */
transform-style: preserve-3d; /* 保持子元素在 3D 空间内 */
}
.card {
transform: rotateY(180deg); /* 绕 Y 轴翻转 */
backface-visibility: hidden; /* 翻转后隐藏背面 */
}
3D 平移:translateZ(50px)(向屏幕外移动)、translate3d(x, y, z)。3D 旋转:rotateX() / rotateY() / rotate3d()。
注意:transform 多个函数的书写顺序影响最终结果------先右乘 ,书写靠右的函数先执行。transform: rotate(45deg) translateX(100px) 与 translateX(100px) rotate(45deg) 结果不同,因为前者先移动再旋转(移动方向已偏转 45 度)。
常见模式
绝对居中(宽高未知):
css
.center {
position: absolute;
top: 50%; left: 50%;
transform: translate(-50%, -50%);
}
卡片 hover 浮起:
css
.card:hover { transform: translateY(-4px); }
卡片翻转:
css
.card-inner {
transition: transform .6s;
transform-style: preserve-3d;
}
.card:hover .card-inner { transform: rotateY(180deg); }
.front, .back { backface-visibility: hidden; }
.back { transform: rotateY(180deg); }
五、动画
CSS 动效分两层:过渡 描述属性值变化的平滑过程,关键帧动画定义多阶段状态序列。
transition:过渡
当元素属性值发生变化时(如 hover、class 切换),过渡让变化平滑展开。
css
.box {
transition-property: opacity, transform; /* 参与过渡的属性 */
transition-duration: .3s, .5s; /* 对应时长 */
transition-timing-function: ease; /* 缓动函数 */
transition-delay: 0s; /* 延迟 */
/* 简写:transition: opacity .3s ease, transform .5s ease; */
}
常用 timing-function:
| 值 | 特征 | 场景 |
|---|---|---|
ease |
快起 → 慢 → 慢停(默认) | 大多数 UI 过渡 |
linear |
匀速 | 颜色渐变、无限旋转动画 |
ease-in-out |
慢起 → 快 → 慢停 | 模态框出入 |
cubic-bezier(.4, 0, .2, 1) |
自定义曲线 | 需要精确控制节奏时 |
注意:并非所有属性都能过渡。display、background-image(渐变除外)等不可过渡;能过渡的包括 opacity、transform、color、width/height 等数值型属性。优先过渡 opacity 和 transform------它们只触发合成阶段,性能最优,不引起重排。
过渡触发后立即完成,无法暂停或循环。需要更复杂的控制时用 animation。
animation:关键帧动画
css
/* 定义 */
@keyframes fadeIn {
from { opacity: 0; transform: translateY(10px); }
to { opacity: 1; transform: translateY(0); }
}
/* 使用 */
.element {
animation-name: fadeIn;
animation-duration: .4s;
animation-timing-function: ease;
animation-delay: 0s;
animation-iteration-count: 1; /* infinite 无限循环 */
animation-direction: normal; /* alternate 交替反向 */
animation-fill-mode: forwards; /* 结束后保持终态 */
animation-play-state: running; /* paused 暂停 */
/* 简写:animation: fadeIn .4s ease forwards; */
}
关键属性解析:
animation-fill-mode: forwards:动画结束后保留最后一帧状态,避免跳回初始值。日常使用率极高。animation-play-state: paused:hover 时暂停动画,常用于轮播和加载指示器。animation-direction: alternate:奇数次正向,偶数次反向,配合infinite实现来回动画。
@keyframes 百分比
多阶段动画用百分比:
css
@keyframes shimmer {
0% { background-position: -200% 0; }
100% { background-position: 200% 0; }
}
常见模式
淡入 + 滑入:
css
@keyframes fadeInUp {
from { opacity: 0; transform: translateY(20px); }
to { opacity: 1; transform: translateY(0); }
}
无限旋转(loading):
css
@keyframes spin {
to { transform: rotate(360deg); }
}
.spinner { animation: spin .8s linear infinite; }
骨架屏闪烁:
css
@keyframes shimmer {
100% { background-position: 200% 0; }
}
.skeleton {
background: linear-gradient(90deg, #eee 25%, #f5f5f5 50%, #eee 75%);
background-size: 200% 100%;
animation: shimmer 1.5s infinite;
}
hover 时的过渡暂停与恢复:
css
.carousel { animation: slide 10s linear infinite; }
.carousel:hover { animation-play-state: paused; } /* hover 暂停轮播 */
总结
- 定位处理元素与文档流的关系------脱离流(absolute/fixed)、半脱离(sticky)、微调(relative)和层叠(z-index)。
- Grid 处理二维布局------用轨道定义(
grid-template-*)画结构,用fr/auto-fill/minmax做响应式,用grid-area命名语义化。 - 多列 处理长文本排版------用
column-count/column-width分列,column-rule分隔,break-inside: avoid防断裂。 - 变换 在合成阶段调整视觉------用
translate/rotate/scale做 2D 变形,加perspective+preserve-3d进入 3D。 - 过渡 和动画 处理时间维度------过渡管"从 A 到 B"的平滑,动画管"多阶段循环"的编排。优先操作
opacity和transform保性能。