Skip to content

第 02 章 · CSS 基础

一句话开篇:CSS 是网页的「装修队」——HTML 立好了毛坯房,CSS 决定刷什么颜色、铺什么地砖、家具怎么摆。


0. 生活类比(先建立直觉)

把 CSS 想象成给房子做装修

场景HTMLCSS
立钢筋墙<div class="room">
选墙漆颜色background-color: #fff;
决定客厅 / 卧室大小width: 300px; height: 200px;
沙发摆中间还是靠墙positionflexgrid
挂画 hover 时变亮:hovertransition
大屏幕和手机看到不一样的家媒体查询(@media

CSS 的全称是 Cascading Style Sheets(层叠样式表)

  • 层叠(Cascade):多条规则同时作用同一个元素时,按"权重 + 顺序"决定谁说了算(就像家里 3 个长辈意见不一致,要按辈分定)。
  • 样式(Style):管颜色、大小、位置、动画。
  • 样式表(Sheet):一张写满规则的"装修清单"。

学 CSS 最重要的是建立空间感:每个元素都是一个长方形盒子,CSS 就是给这些盒子排队、上色、摆姿势。


1. 概念是什么

1.1 写 CSS 的 3 种方式

方式写法适用优先级
行内样式<div style="color:red">临时调试
内部样式<style>...</style> 写在 head单页 demo
外部样式<link rel="stylesheet" href="x.css">实际项目

1.2 一条规则的解剖

选择器 {
  属性: 值;
  属性: 值;
}
css
h1 {              /* 选择器 */
  color: red;     /* 声明:属性: 值 */
  font-size: 24px;
}

一行 CSS = 给"哪些元素"应用"什么样式"。


2. 为什么需要它

只有 HTML 的网页:黑底白字、上下排列、所有按钮长得一样、PC 和手机看到完全相同的丑样。

CSS 解决了 4 件事:

  1. 结构与样式分离:HTML 专心描述"是什么",CSS 专心描述"长什么样"。
  2. 复用:一处改色,全站换肤。
  3. 响应式:一份代码,PC / 平板 / 手机自适应。
  4. 动效:让按钮"按下去"有反馈,让弹窗"飘进来",提升用户体验。

没有 CSS 的网页就像没装修的毛坯房——能住,但你不想住。


3. 怎么用(最小示例)

html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8" />
  <style>
    body { background: #f9fafb; font-family: sans-serif; }
    h1   { color: #2563eb; text-align: center; }
    .card { background: #fff; padding: 16px; border-radius: 8px; box-shadow: 0 2px 6px rgba(0,0,0,.1); }
  </style>
</head>
<body>
  <h1>你好,CSS</h1>
  <div class="card">这是一张卡片</div>
</body>
</html>

4. 进阶要点

4.1 选择器(重头戏)

类型写法含义权重
通配符*所有元素0,0,0,0
标签h1, p所有该标签0,0,0,1
.btn所有 class 含 btn 的元素0,0,1,0
ID#headerid="header" 的元素(唯一)0,1,0,0
属性input[type=text]type 等于 text 的 input0,0,1,0
伪类a:hover, li:first-child元素的特定状态0,0,1,0
伪元素p::before, p::after虚拟生成的子元素0,0,0,1
行内 stylestyle="..."直接写在标签上1,0,0,0
!importantcolor: red !important强制最高

组合选择器

css
/* 后代(空格):article 内的所有 p(包括嵌套深层) */
article p { color: gray; }

/* 子选择器(>):article 的直接子级 p */
article > p { font-weight: bold; }

/* 相邻兄弟(+):紧跟 h2 的下一个 p */
h2 + p { margin-top: 0; }

/* 通用兄弟(~):h2 后所有同级 p */
h2 ~ p { color: green; }

/* 群组(,):h1 和 h2 都用这个样式 */
h1, h2 { font-family: serif; }

/* 同时满足:class 是 btn 且是 a 标签 */
a.btn { padding: 8px 16px; }

常用伪类

css
a:link    { color: blue; }     /* 未访问 */
a:visited { color: purple; }   /* 已访问 */
a:hover   { color: red; }      /* 鼠标悬停 */
a:active  { color: orange; }   /* 按下瞬间 */

input:focus    { border-color: blue; }
input:disabled { background: #eee; }
input:checked  { /* checkbox / radio 选中 */ }

li:first-child  { color: red; }
li:last-child   { color: blue; }
li:nth-child(2) { color: green; }
li:nth-child(odd)  { background: #f9f9f9; }  /* 奇数 */
li:nth-child(even) { background: #fff; }     /* 偶数 */

p:not(.special) { color: black; }  /* 不是 .special 的 p */

伪元素(注意是双冒号 ::):

css
p::before { content: "👉 "; }   /* 在 p 内容前插入 */
p::after  { content: " 完"; }   /* 在 p 内容后插入 */
p::first-letter { font-size: 2em; }   /* 首字下沉 */
p::first-line   { font-weight: bold; } /* 第一行加粗 */
::selection     { background: yellow; } /* 鼠标选中文本时 */

4.2 盒模型(最最最重要)

每个元素都是一个矩形盒子,从外到内 4 层:

┌──────────── margin(外边距,与别人保持距离) ────────────┐
│  ┌────────── border(边框) ──────────────────────┐      │
│  │  ┌──────── padding(内边距,内容到边的距离) ───┐  │   │
│  │  │  ┌──────────────────────────────────┐      │  │   │
│  │  │  │         content(内容)           │      │  │   │
│  │  │  │      width × height               │      │  │   │
│  │  │  └──────────────────────────────────┘      │  │   │
│  │  └──────────────────────────────────────────────┘  │   │
│  └────────────────────────────────────────────────────┘   │
└────────────────────────────────────────────────────────────┘

两种盒模型

box-sizingwidth 含义实际占位
content-box(默认)只算 contentwidth + padding + border
border-boxcontent + padding + border就是 width
css
/* 现代项目几乎都加这一行:让 width 包含 padding 和 border */
* { box-sizing: border-box; }

margin 折叠(坑):

两个垂直方向相邻的元素,margin 不会叠加,而是取最大值

css
.a { margin-bottom: 30px; }
.b { margin-top: 20px; }
/* a 和 b 之间的距离不是 50px,而是 30px! */

4.3 定位(position)

含义类比
static(默认)跟随文档流排队站好
relative相对自己原来位置偏移站着不动,但叫人"看我从右移 10cm"
absolute相对最近的"非 static 父元素"定位像便利贴粘到墙上
fixed相对浏览器窗口固定像贴在车窗上的吸盘玩偶,车开它不动
sticky滚动到某位置后吸顶表头吸顶
css
.parent   { position: relative; }            /* 给绝对定位的子元素当"地基" */
.child    { position: absolute; top: 0; right: 0; }  /* 钉在父元素右上角 */
.fixed-btn { position: fixed; bottom: 20px; right: 20px; } /* 始终右下角 */
.sticky-h { position: sticky; top: 0; }      /* 滚到顶就吸住 */

z-index:层级(数字越大越在上面)。只对非 static 元素生效

4.4 Flexbox(一维布局神器)

把容器变成 flex container,子元素自动按"一行"或"一列"排列。

父元素(display: flex)
┌───────────────────────────────────────────┐
│  ┌────┐  ┌────┐  ┌────┐  ┌────┐           │ → 主轴方向
│  │子1 │  │子2 │  │子3 │  │子4 │           │
│  └────┘  └────┘  └────┘  └────┘           │
└───────────────────────────────────────────┘

容器属性

属性含义
displayflex启用 flex
flex-directionrow / row-reverse / column / column-reverse主轴方向
justify-contentflex-start / center / flex-end / space-between / space-around / space-evenly主轴对齐
align-itemsstretch(默认) / center / flex-start / flex-end / baseline交叉轴对齐
flex-wrapnowrap(默认) / wrap换不换行
gap数值子元素间距

子元素属性

属性含义
flex-grow剩余空间分配比例(默认 0,不占)
flex-shrink空间不够时缩小比例(默认 1)
flex-basis初始宽度
flex简写,常用 flex: 1(= grow:1 shrink:1 basis:0)
align-self单独覆盖父级的 align-items
order排序(默认 0,越小越靠前)

经典需求

css
/* 水平垂直居中(曾经是面试重灾区,现在 3 行搞定) */
.center {
  display: flex;
  justify-content: center;
  align-items: center;
}

/* 左右两端布局 */
.nav {
  display: flex;
  justify-content: space-between;
}

/* 三栏,中间自适应 */
.layout > .side  { width: 200px; }
.layout > .main  { flex: 1; }

4.5 Grid(二维布局神器)

Flex 是"一行排队",Grid 是"棋盘式"——同时控制行和列。

css
.container {
  display: grid;
  grid-template-columns: 200px 1fr 1fr;       /* 3 列:200px、1份、1份 */
  grid-template-rows: 80px auto 60px;          /* 3 行 */
  gap: 12px;                                    /* 行列间距 */
}

fr 单位:剩余空间的"份数"。1fr 2fr = 1:2 分配剩余。

响应式网格(一行搞定卡片墙自适应):

css
.cards {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  gap: 16px;
}

含义:自动填充列,每列最小 200px,最大 1fr。窗口变窄时自动减少列数。

命名区域(最直观的写法):

css
.layout {
  display: grid;
  grid-template-areas:
    "header header"
    "side   main"
    "footer footer";
  grid-template-columns: 200px 1fr;
}
.layout > header { grid-area: header; }
.layout > .side  { grid-area: side; }
.layout > .main  { grid-area: main; }
.layout > footer { grid-area: footer; }

4.6 Flex vs Grid 对比

维度FlexGrid
维度一维(行 或 列)二维(行 和 列)
适用导航栏、按钮组、单列列表整页布局、卡片墙、复杂表格
关注点子元素如何排队容器如何分格
学习曲线简单中等
兼容性极好现代浏览器都支持

经验法则:整页布局用 Grid,组件内部用 Flex。

4.7 响应式(媒体查询)

css
/* 默认:手机优先样式 */
.container { width: 100%; }

/* 平板(≥768px) */
@media (min-width: 768px) {
  .container { width: 720px; margin: 0 auto; }
}

/* PC(≥1024px) */
@media (min-width: 1024px) {
  .container { width: 960px; }
}

常用断点(参考 Bootstrap 5):

设备断点
超小(手机)< 576px
小(大手机)≥ 576px
中(平板)≥ 768px
大(桌面)≥ 992px
超大(大桌面)≥ 1200px
超超大≥ 1400px

移动优先 vs 桌面优先

  • 移动优先:默认写手机样式,用 min-width 加大屏样式(推荐)。
  • 桌面优先:默认写桌面样式,用 max-width 加小屏样式。

4.8 单位

单位含义适用
px像素(绝对)边框、阴影
%父元素的百分比弹性宽度
em当前字号的倍数间距
rem根字号(html 的 font-size)的倍数全站缩放
vw / vh视口宽 / 高的 1%全屏布局
frgrid 中的"份"grid 列宽

rem 全站缩放套路

css
html { font-size: 16px; }
body { font-size: 1rem; }
h1   { font-size: 2rem; }   /* 32px */
.card { padding: 1.5rem; }  /* 24px */

/* 改一处,全站等比例缩放 */
@media (max-width: 480px) { html { font-size: 14px; } }

4.9 动画

transition(过渡):从 A 状态平滑变到 B 状态。

css
.btn {
  background: #2563eb;
  transition: background 0.3s ease, transform 0.2s;
}
.btn:hover {
  background: #1d4ed8;
  transform: translateY(-2px);
}

transition 4 件套property duration timing-function delay

transform 常用变换

函数作用
translate(x, y)平移
rotate(45deg)旋转
scale(1.2)缩放
skew(10deg)倾斜

animation(关键帧动画):可循环、可暂停。

css
@keyframes shake {
  0%, 100% { transform: translateX(0); }
  25%      { transform: translateX(-8px); }
  75%      { transform: translateX(8px); }
}
.error {
  animation: shake 0.4s;
}

timing-functionease(默认)/ linear / ease-in / ease-out / ease-in-out / cubic-bezier(...)

4.10 颜色与背景

css
color: red;                          /* 关键字 */
color: #ff0000;                      /* 16 进制 */
color: rgb(255, 0, 0);
color: rgba(255, 0, 0, 0.5);         /* 带透明度 */
color: hsl(0, 100%, 50%);            /* 色相、饱和度、亮度 */

background-color: #f9fafb;
background-image: url('bg.jpg');
background: linear-gradient(135deg, #6366f1, #8b5cf6);   /* 渐变 */
background: radial-gradient(circle, #fff, #ddd);

box-shadow: 0 2px 8px rgba(0,0,0,.1);   /* 阴影 */
border-radius: 8px;                       /* 圆角 */

5. 实战案例

详见 examples/ 目录:

  • box-model.html — 盒模型可视化
  • flexbox.html — Flex 各种对齐演示
  • grid.html — Grid 经典布局
  • animation.html — 过渡 + 关键帧动画
  • responsive.html — 媒体查询响应式

完整 demo 见 demo/index.html:响应式商品卡片墙。


6. ⚠️ 易踩的坑

坑 1:忘了 box-sizing: border-box

默认 width 不含 padding 和 border,导致"明明设了 200px,加 padding 后变 220px"——布局算不准。新项目第一行写

css
*, *::before, *::after { box-sizing: border-box; }

坑 2:margin 上下折叠

html
<div style="margin-bottom: 30px">A</div>
<div style="margin-top: 20px">B</div>

A 和 B 之间不是 50px,是 30px(取最大值)。解决:用 padding,或加 border、overflow: hidden 等触发 BFC。

坑 3:absolute 找不到正确的"地基"

绝对定位元素是相对最近的非 static 父元素定位。如果父元素都没设 position,会一路找到 body。

口诀:子绝对,父相对(.parent { position: relative; })。

坑 4:z-index 不生效

z-index 只对非 static 元素生效。常忘记给 .modalposition: fixed/absolute

坑 5:!important 滥用

新手遇到样式不生效就加 !important,最后一堆 !important 互相打架。先想优先级,再想权重,最后才用 important

坑 6:选择器权重计算错误

css
#a .b p     { color: red; }    /* 0,1,1,1 */
.x .y .z p  { color: blue; }   /* 0,0,3,1 */
/* id > 多个 class,红色赢 */

记住:(行内, id, class/伪类/属性, 标签/伪元素)

坑 7:行内元素设宽高无效

css
span { width: 100px; }   /* ❌ 无效 */
span { display: inline-block; width: 100px; } /* ✅ */

坑 8:图片下方有 3px 缝隙

img 是行内元素,受 vertical-align: baseline 影响,底部有空隙。

css
img { display: block; }  /* 或 vertical-align: middle */

坑 9:忘了 viewport meta,写了响应式也没用

html
<meta name="viewport" content="width=device-width, initial-scale=1.0" />

不写这一行,手机会按 980px 缩放,媒体查询永远命中桌面分支。

坑 10:用 background-color 给图标着色

background-color 只能改背景色,改不了 SVG/字体图标的颜色。SVG 用 fill,字体图标用 color

坑 11:动画导致页面卡顿

width / height / top / left 会触发 重排(reflow),性能差。改用 transform(平移、缩放)和 opacity,由 GPU 加速。

css
/* ❌ 卡 */
.box { left: 0; transition: left 0.3s; }
.box:hover { left: 10px; }

/* ✅ 顺滑 */
.box { transform: translateX(0); transition: transform 0.3s; }
.box:hover { transform: translateX(10px); }

坑 12:Flex 子元素 flex: 1 不等宽

flex: 1 等价于 flex: 1 1 0,从 0 开始按比例生长,等宽。 但如果用 flex: 1 1 auto,从内容宽度开始生长,内容多的更宽


7. 一句话总结

CSS 是给 HTML 装修:选对盒模型、玩转 Flex 和 Grid、记住权重和层叠规则,再配合媒体查询和动画——你就能让网页在任何屏幕上都漂亮又流畅。


8. 延伸阅读