CSS:选择器、盒模型与布局系统
这一课你将能做到
- 写出现代 CSS 选择器,精准命中页面中的任意元素
- 用盒模型、flex 和 grid 三种方式控制元素的大小和位置
- 搭建一个完整的响应式页面,包含媒体查询和基础过渡动画
为什么要学
HTML 搭好了骨架,但所有网站都是「素颜」的白纸黑字。CSS 负责颜色、间距、排版、位置,也负责让同一套代码在手机、平板、电脑上看起来都对劲。不会 CSS,你就只能做出 90 年代的网页。
对初学者来说,CSS 的坑在于:它看起来很简单(就是改样式),但背后有层叠、优先级、盒模型、定位上下文等多个独立维度互相干扰。很多初学者写的样式「为什么不生效」或「为什么多了一像素」,本质上是对盒模型和层叠理解不到位。
先建立图像
浏览器把每个 HTML 元素都渲染成一个矩形盒子。盒子的构成从外到内:
┌─────────────────────────────────┐
│ margin(外边距) │
│ ┌─────────────────────────────┐│
│ │ border(边框) ││
│ │ ┌───────────────────────┐ ││
│ │ │ padding(内边距) │ ││
│ │ │ ┌─────────────────┐ │ ││
│ │ │ │ content │ │ ││
│ │ │ │ 宽 × 高 │ │ ││
│ │ │ └─────────────────┘ │ ││
│ │ └───────────────────────┘ ││
│ └─────────────────────────────┘│
└─────────────────────────────────┘
默认情况下你写的 width 和 height 只是 content 区域。CSS3 引入了 box-sizing: border-box,让 width/height 直接代表整个可见盒子的大小——这是现代开发的标准做法。
跟着做
步骤 1:重置默认样式并理解盒模型
新建 style.css,写入:
/* 让所有元素按 border-box 计算,现代项目标配 */
*,
*::before,
*::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.box {
width: 200px;
height: 100px;
padding: 20px;
border: 5px solid #333;
margin: 15px;
background-color: #f0f0f0;
}
在 index.html 中引入:
<head>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="box">内容区</div>
</body>
.box 的总渲染宽度是 200px(width)+ 0 padding/border/margin 不算入,因为用了 border-box。删掉 box-sizing 行再试,宽度会变成 250px(200 + 20×2 + 5×2),这就是标准盒模型的经典陷阱。
步骤 2:选择器层级练习
/* 1. 元素选择器 */
h1 {
color: #1a1a1a;
}
/* 2. 类选择器 */
.card {
background: white;
border-radius: 8px;
}
/* 3. ID 选择器 */
#hero {
min-height: 400px;
}
/* 4. 后代选择器:nav 里的所有 a */
nav a {
text-decoration: none;
}
/* 5. 子选择器:ul 的直接子 li */
ul > li {
list-style: none;
}
/* 6. 相邻兄弟 */
h2 + p {
margin-top: 0.5rem;
}
/* 7. 伪类 */
a:hover {
color: #e63946;
}
li:nth-child(odd) {
background: #f8f9fa;
}
/* 8. 伪元素 */
h1::after {
content: "!";
color: #e63946;
}
class 优先级 0-1-0,id 是 1-0-0,内联样式(style="")是 1-0-0-0。优先级冲突时数字大的赢。多记一个规则:优先级相同,后写的覆盖先写的。
步骤 3:Flex 布局
Flex 是目前最常用的布局方式,用于一维排列(一行或一列):
.container {
display: flex;
gap: 16px;
flex-wrap: wrap;
justify-content: center; /* 主轴对齐 */
align-items: center; /* 交叉轴对齐 */
}
.item {
flex: 1 1 200px; /* 可放大、可缩小、基准 200px */
min-height: 120px;
background: #dee2e6;
display: flex;
align-items: center;
justify-content: center;
}
<div class="container">
<div class="item">A</div>
<div class="item">B</div>
<div class="item">C</div>
</div>
justify-content:主轴对齐(默认 row 时就是水平方向)
align-items:交叉轴对齐(默认 row 时就是垂直方向)
flex-wrap: wrap:空间不够时自动换行,不写的话子元素会被压扁
步骤 4:Grid 布局
Grid 用于二维布局(同时控制行和列),适合仪表盘、图片画廊、整体页面骨架:
.grid-container {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 16px;
}
.grid-item:first-child {
grid-column: span 2; /* 第一个元素占两列 */
}
<div class="grid-container">
<div class="grid-item">占两列</div>
<div class="grid-item">B</div>
<div class="grid-item">C</div>
<div class="grid-item">D</div>
<div class="grid-item">E</div>
</div>
repeat(3, 1fr) 表示三列等宽;1fr 是「一份剩余空间」。如果要实现侧边栏固定、主内容自适应:grid-template-columns: 250px 1fr。
步骤 5:定位
/* 相对定位:相对于自己原本的位置偏移 */
.relative-box {
position: relative;
top: 10px;
left: 10px;
}
/* 绝对定位:相对于最近的非 static 祖先元素 */
.parent {
position: relative;
}
.absolute-box {
position: absolute;
top: 0;
right: 0;
}
/* 固定定位:相对于视口 */
.fixed-header {
position: fixed;
top: 0;
width: 100%;
z-index: 1000;
}
绝对定位会脱离文档流,不占据原来的空间;相对定位不会脱离,只是视觉上偏移。z-index 只在定位元素(非 static)上有效。
步骤 6:响应式基础
.container {
padding: 16px;
max-width: 1200px;
margin: 0 auto;
}
/* 手机优先:小屏幕默认,大屏幕覆盖 */
@media (min-width: 768px) {
.container {
padding: 32px;
}
}
@media (min-width: 1024px) {
.grid-container {
grid-template-columns: repeat(4, 1fr);
}
}
现代前端普遍采用「移动优先」写法:先写手机样式,再用 min-width 媒体查询叠加桌面样式。这样加载的 CSS 更少,逻辑也更清晰。
步骤 7:基础过渡动画
.button {
background: #4361ee;
color: white;
padding: 12px 24px;
border: none;
border-radius: 6px;
transition: background 0.3s ease, transform 0.2s ease;
cursor: pointer;
}
.button:hover {
background: #3a0ca3;
transform: translateY(-2px);
}
transition 写在默认状态上,这样悬停和离开都有过渡效果。
讲清楚要点
- 盒模型是一切的基础:
content-box(默认,width 只含 content)vs border-box(width 含 content + padding + border)。现代项目通配符重置 border-box 是行业惯例。
- 层叠和优先级决定「谁生效」:不是后写一定赢,而是优先级高者赢。
!important 是核武器,只在覆盖第三方库或临时调试时用,禁止在自己代码里滥用。
- Flex 管一维,Grid 管二维:简单横向/纵向排列用 Flex;同时需要行列控制的复杂布局用 Grid。
- 定位要理解「参照物」:relative 参照自己,absolute 参照最近的定位祖先,fixed 参照视口。没有定位祖先时 absolute 会一路追到 body。
- 响应式不是写两套页面:是同一套代码在不同断点(breakpoint)做渐进增强。常用断点:768px(平板)、1024px(小桌面)、1280px(桌面)。
你可能会懵的地方
-
为什么我的样式不生效?
按这个顺序排查:选择器写错(类名拼写)→ 优先级不够(被覆盖)→ 属性拼写错误 → 浏览器缓存(Ctrl+F5)。
-
margin 的上下边距会合并?
是的。垂直相邻块级元素的 margin-top 和 margin-bottom 不会相加,而是取最大值。这是 CSS 的标准行为,用 Flex 的 gap 或只用一个方向的 margin 来规避。
-
flex: 1 到底是什么意思?
flex: 1 是 flex-grow: 1; flex-shrink: 1; flex-basis: 0% 的简写。意思是「我参与分配剩余空间,基准大小为 0」。
-
百分比宽度是相对于谁?
相对于直接父元素的内容区宽度。如果父元素没有显式宽度,百分比可能无效。width: 100% 加 padding 在不设 border-box 时会撑破容器。
-
Grid 和 Flex 能不能嵌套?
完全可以。一个 grid item 里面放 flex container,或者反过来,都是常见做法。没有性能问题,放心用。
错法对照
| 错法 | 问题 | 正解 |
|---|
width: 100% + padding 不用 border-box | 实际宽度超过父容器 | 通配符重置 border-box |
滥用 !important | 优先级不可控,后期无法覆盖 | 用更高特异性的选择器 |
用 float 做页面布局 | 浮动原本用于图文混排,做布局难维护 | 用 Flex/Grid |
定位元素不写 z-index | 层叠顺序由 DOM 顺序决定,难以预期 | 显式设置 z-index |
垂直居中用 margin: auto | 只对水平方向生效 | 用 Flex 的 align-items: center |
所有元素都设 height: 100% | 内容撑不开,溢出截断 | 内容撑开高度,容器用 min-height |
媒体查询写一堆 max-width | 逻辑混乱,CSS 冗余 | 移动优先,用 min-width 渐进增强 |
卡点急救
- 样式改了不生效:F12 的 Elements 面板看对应元素,右侧 Styles 会显示生效规则和被打叉的规则;被打叉的规则就是优先级不够或被覆盖。
- 元素位置不对:F12 → Computed → 看盒模型示意图,确认 margin/padding/border 各是多少。
- Flex 子元素被压扁:给子元素加
min-width: 0(防止内容撑开)或给容器加 flex-wrap: wrap。
- Grid 出现意外的空白列:
grid-template-columns 定义的列数与实际 item 数量不匹配,检查 HTML 结构。
面试常问
-
盒模型是什么?标准盒模型和 IE 盒模型的区别?
标准模型下 width/height 只含 content;IE 模型(即 border-box)下含 content + padding + border。现代开发通配符设置 box-sizing: border-box 就是为了统一用 IE 模型。
-
BFC 是什么?怎么创建?
BFC(Block Formatting Context)是一块独立的渲染区域,内部布局不影响外部。创建方式:float 不为 none、position 为 absolute/fixed、display 为 inline-block/flex/grid、overflow 不为 visible。经典应用:清除浮动、防止 margin 合并、阻止文字环绕浮动。
-
居中一个元素有多少种方法?
至少三种:1) Flex:justify-content: center; align-items: center;2) Grid:place-items: center;3) 绝对定位 + transform: translate(-50%, -50%)。
-
rem、em、px 的区别?
px 是绝对单位;em 相对于父元素字体大小;rem 相对于根元素(html)字体大小。现代响应式项目推荐 rem + 根元素动态字体大小。
自测三问
box-sizing: border-box 到底改变了什么计算规则?
- 写一段 Flex 代码,实现「三个卡片等宽,间距 16px,超出换行」。
position: absolute 的参照物是谁?如果没有定位祖先会怎样?
小结一句话
CSS 的核心是「选得到、放得下、排得齐」——选择器命中目标、盒模型控制尺寸、Flex/Grid 控制位置,三者叠加就能做出任何现代页面布局。
延伸
- MDN CSS 基础
- 下一课:JavaScript——让页面动起来,学会变量、函数、DOM 操作和事件监听。