HTML 和 CSS 这对组合,一个负责内容结构,一个负责长相气质。上一篇把 HTML 的骨架过了一遍,这篇就集中火力啃 CSS 这块硬骨头。很多人学 CSS 总觉得知识点零散,今天学个颜色明天学个边框,结果真到写页面的时候,还是不知道怎么把一个卡片摆得横平竖直、间距舒舒服服。这篇教程不讲虚的,直接从 CSS 的核心机制讲起,把选择器、盒模型、布局、响应式这些高频场景一次性捋清楚,配着实际代码一步步来,学完你至少能独立写出一个像样的静态页面。适合刚入门或者学了半吊子想系统补一遍的同学。
CSS 这个缩写对应的是层叠样式表,名字里的“层叠”和“样式”两个词就点出了本质。它要解决的核心问题,就是把 HTML 里那堆语义化标签,变成人眼看起来有层次、有节奏、有美感的视觉页面。没有 CSS 的网页,就像一份没有格式的 Word 文档,标题和正文连在一起,毫无可读性。有了 CSS,你才能控制字体大小、颜色、间距、背景、排版布局,甚至做动画。这篇文章的核心目标,就是帮你建立对 CSS 的整体认知框架,而不是像查字典一样记住每个属性。
1. 先搞清楚CSS到底解决什么问题
CSS 存在的意义,可以理解成“内容与表现分离”。HTML 负责告诉浏览器“这里是一级标题,那里是一个段落”,CSS 则负责告诉浏览器“一级标题用多大字号、什么颜色、左边留多少空白”。这种分离带来一个直接的好处:你可以通过修改一份样式文件,让整个网站几百个页面的风格统一变化,而不用去改动每一个 HTML 文件。这也是为什么绝大多数网站的样式都抽离成独立的外部样式表,而不是写死在标签属性里。
但很多初学者会忽略一个关键认知:CSS 的“样式”并不是机械地逐条套用规则,它有一套自己的冲突解决机制。同一个元素,可能被多个规则命中,比如浏览器默认样式、你自己写的 class、内联 style,它们之间到底听谁的?这就引出了 CSS 最核心的三个机制——层叠、继承、优先级。不理解这三者,你会陷入“为什么我写了样式就是不生效”的泥潭里。
1.1 没有 CSS 的网页长什么样
先做一个直观实验。在一个空白 HTML 文件里写几个标签,不引入任何样式,然后再加一段 CSS 对比效果。你会看到,浏览器其实自带一套默认样式:标题比正文大且加粗、段落之间有默认间距、链接是蓝色带下划线、列表项前有小圆点。这套默认样式叫“用户代理样式”,不同浏览器之间略有差异,这也是为什么社区里流行各种“CSS Reset”或“Normalize.css”——先把这些默认样式清零,让开发在一个相对干净的起点上排版。
我自己带新人时,总喜欢让他们先看无样式版本的页面,因为那能直观理解 HTML 的信息层级。随后再逐步加样式,你会看到 CSS 如何把这些“毛坯”信息变成“精装”视觉。这种从裸奔到穿衣打扮的过程,才是理解 CSS 价值的最佳路径。如果你跳过这一步,直接套现成框架,很快会在样式冲突和“元素对不齐”上栽跟头。
1.2 学习 CSS 的第一个分水岭:盒模型
盒模型是整个 CSS 布局的地基,怎么强调都不过分。任何一个 HTML 元素在渲染时都会被浏览器画成一个矩形盒子,这个盒子由外到内依次为 margin(外边距)、border(边框)、padding(内边距)、content(内容区)。两个元素的间距靠 margin 控制,元素内部文字与边框的距离靠 padding 控制,边框本身用 border 控制,真正的宽度高度则落在 content 上。
这里有一个新手必踩的坑:默认情况下,width 属性定义的是内容区 content 的宽度,而不是盒子的总宽度。假设你设置 width: 300px,padding: 20px,border: 5px,那这个元素实际占的水平空间是 300 + 202 + 52 = 350px。你打算设计两个并排各占一半宽度的元素,结果因为各自加了 padding 和 border,实际总宽度超出容器,导致换行,这类问题几乎每个前端都经历过。
解决方案早就有了,就是设置 box-sizing: border-box。这个属性会把 width 直接定义成整个盒子的总宽度,padding 和 border 都从内部“挤占”空间,而非外部“撑开”宽度。现代开发中,我习惯在 CSS 开头对全局设置 box-sizing: border-box,让所有元素都用这种更符合直觉的计算方式。
1.3 CSS 的层叠与继承机制
“层叠”这个词听起来抽象,但理解后特别简单。浏览器决定一个元素最终样式时,会遵循三个维度的规则:来源优先级、选择器优先级、源码顺序。来源优先级是指浏览器默认样式 < 用户自定义样式 < 作者写的样式,你写的 CSS 天然高于浏览器默认样式。选择器优先级是我们常说的权重(后面详细展开)。源码顺序则是在优先级相同的情况下,后写的覆盖先写的。
继承机制则是另一条轴。某些 CSS 属性(如 color、font-size、line-height)会自动从父元素传递给子元素,这就是继承。你给 body 设置 color: #333,页面里所有文字默认都会变成这种颜色,不需要每个标签单独设置。而另一些属性(如 margin、padding、border、width、height)默认不继承,它们应该影响各自元素盒子的形态,而不是往下传递。
CSS 还提供了几个控制继承的关键字:inherit 强制继承父级值,initial 恢复默认值,unset 表示“有继承就继承,没继承就用初始值”。这些关键字在处理复杂覆盖时很省事,比如希望某个按钮不要继承页面主色,可以直接 color: initial。掌握继承规则,能帮你大幅减少重复代码。
2. 选择器与优先级:写对样式的地基
选择器的作用是告诉你“我要给哪些元素上样式”。如果你连目标都选不中,后面写的属性再漂亮都是白搭。CSS 选择器种类非常多,但日常高频用到的就那十来种。先掌握这些高频的,再慢慢拓展冷门的,否则一上来背几十种选择器,纯属浪费时间。
2.1 高频选择器速览
- 元素选择器:直接写标签名,如
div、p、a。它会选中文档中所有该类标签,适合设置全局基础样式。 - 类选择器:
.class-name,这是最常用的选择器,因为它可以复用,并且和 HTML 的 class 语义对应得很好。 - ID 选择器:
#id-name,选中唯一元素,优先级很高,但正是因为高,后期覆盖麻烦,不推荐作为主要样式入口。 - 后代选择器:
父级 子级,中间用空格,比如.card .title,匹配 .card 内部所有匹配 .title 的后代元素。 - 子代选择器:
父级 > 子级,只匹配直接子元素,不往下穿透。 - 属性选择器:
[type="text"],按 HTML 属性匹配,常用于表单样式。 - 伪类选择器:
:hover、:first-child、:nth-child(2n),匹配元素的特定状态或位置关系。 - 伪元素:
::before、::after,可以在元素内部生成虚拟内容,常用于装饰性效果。
一份真实项目里,类选择器能覆盖百分之八九十的场景。我建议你刚开始时强制自己只用类选择器写样式,等到能熟练写出组件后,再引入其他选择器辅助。这样做的原因是,类选择器目标明确、可复用、优先级适中,也最容易被自己和同事看懂。
2.2 优先级计算:别再靠经验猜
优先级是无数初学者的噩梦。你写了div.title { color: red }和.title { color: blue },哪个生效?答案是 red,因为虽然两个选择器都命中了同一种元素,但div.title的优先级更高——它由元素选择器加一个类选择器组成。
CSS 优先级有一套精确的计算规则,可以把选择器拆成四个维度的计数:(内联样式, ID选择器, 类/属性/伪类选择器, 元素/伪元素选择器)。例如.title是 (0, 0, 1, 0),div.title是 (0, 0, 1, 1),#header .title是 (0, 1, 1, 0)。比较时从左到右逐位比大小,任何一位大就获胜,不再看后面的位数。内联 style 的 (1, 0, 0, 0) 大于一切选择器,而!important可以凌驾于内联样式之上,但滥用它就是给自己埋雷。
我见过很多新人解决样式冲突的方式是无限叠加选择器,比如body #main .container .card .title,一层套一层。结果就是优先级越来越高,后期改任何东西都必须用更多嵌套去压,代码越来越恶心。正确的做法是:尽量使用单类选择器,保持选择器层级不超过三层,如果某个样式需要被组件内部覆盖,通过调整类名结构而不是堆优先级。
2.3 类名命名与组织思路
把选择器用熟之后,会面临一个新问题:类名怎么起。当年我也经历过.red-text-1、.left-box-2这类灾难命名,改一次需求就改一遍名字。后来接触到 BEM 命名思想——Block(块)、Element(元素)、Modifier(修饰符),中文就是“块、元素、修饰符”,一个典型的命名如.card__title--highlight。Block 表示独立组件,Element 表示组件内的组成部分,Modifier 表示该部分的形态变化。这样的命名天然自带了层级关系,看到类名就知道它属于哪个组件、负责什么角色。
我自己用 BEM 时通常不追求百分百严格,而是提炼出几个原则:以组件为命名边界(.card)、组件内部子元素用双下划线连接(.card__title)、状态或变体用双横线连接(.card__title--active)。同时尽量避免纯表现型的名字,比如.red或.bold,因为需求一变,你就要到处改类名。相比之下.price或.highlight这种语义化名字更稳定。
3. 布局实战:从文档流到现代布局
如果说选择器是“找目标”,那布局就是“摆位置”。这是 CSS 里让新手最头痛、也最有成就感的部分。过去布局靠 float 和 table,后来又流行各种负 margin 艺术,现在 Flex 和 Grid 已是绝对主流。我的建议是:跳过后面的复杂坑,直接从 Flex 和 Grid 入手,但在此之前,你还是要理解文档流,因为那是布局的基本盘。
3.1 文档流与 display 切换
文档流是页面的默认排列规律:块级元素(div、p、h1)从上往下堆叠,行内元素(span、a、strong)从左往右排列,碰到边界换行。大多数布局问题,本质上都是你试图脱离这种默认流,或者改变某个元素的“角色”。
Display 属性就是切换角色的开关:
block:让元素变成块级,独占一行,可设置宽高。inline:变成行内元素,不能设置宽高,宽度由内容决定。inline-block:行内排列,但保留宽高、margin、padding 的设置能力。flex:把一个元素变成弹性容器,它的子元素自动进入弹性布局模式。grid:变成网格容器,子元素按行列对齐。none:让元素不占位地消失,不同于 visibility: hidden(仅仅隐藏,但保留空间)。
我从教新人的经验来看,把 display 的几种形态彻底玩明白,大概就解决了一半的布局问题。尤其要理解 inline-block 已经不推荐用来做复杂布局,它的使命被 Flex 接替。但 inline-block 在简单的横向排列场景里依然顺手,比如按钮组或者标签列表。
3.2 定位的四种模式
Position 属性用于让元素脱离文档流,或者相对某个参照点偏移。它有五种取值:static(默认)、relative、absolute、fixed、sticky。
- relative 是相对元素原本所在位置偏移,元素仍然占据文档流空间。
- absolute 是完全脱离文档流,相对最近的“定位祖先”(即 position 非 static 的祖先)进行定位。所以经典的套路是:父容器设置 position: relative,子元素设置 position: absolute,子元素就能以父容器为坐标基准移动。
- fixed 是相对浏览器视口固定,页面滚动时它不动,常用于返回顶部按钮、导航栏。
- sticky 是混合体,它开始时在文档流里正常排列,等滚动到阈值时就“粘”在那里,常用于吸顶导航。
实际布局中,大部分场景根本不需要定位。Flex 和 Grid 已经覆盖了绝大多数的对齐需求。定位主要用于叠加层、弹窗、浮层、图标角标这类元素重叠的场景。如果你发现自己为了对齐几个元素开始滥用 absolute,那多半是布局方案选错了,应该回头检查是否可以用 Flex 或 Grid 更优雅地解决。
3.3 Flex 布局实战
Flex 是目前最值得优先掌握的布局方式。它的核心思路是:让父容器(flex container)决定子项(flex item)如何排列。把父容器设置成 display: flex 后,子项默认沿主轴(默认水平方向)排成一行。
常用属性分两派:设给父容器的和设给子项的。
- 父容器:flex-direction(主轴方向)、justify-content(主轴对齐)、align-items(交叉轴对齐)、flex-wrap(是否换行)、gap(间距)。
- 子项:flex-grow(空间有余时如何扩大)、flex-shrink(空间不足时如何缩小)、flex-basis(初始尺寸)、align-self(单独调整对齐)。
举一个最常见的例子,让三个卡片等分宽度并水平居中:
.container { display: flex; justify-content: center; gap: 20px; } .card { flex: 1; max-width: 300px; }这里的 flex: 1 是 flex-grow: 1、flex-shrink: 1、flex-basis: 0% 的缩写,表示每个卡片平分剩余空间。Flex 最让我喜欢的一点是,它天然解决了“垂直居中”这个古代前端的天大难题,三行代码搞定:
.parent { display: flex; align-items: center; justify-content: center; }3.4 Grid 布局实战
如果 Flex 是一维布局(处理一行或一列),Grid 则是真正的二维布局(同时处理行和列)。它适合页面大框架的划分,比如整体侧边栏加内容区、多列卡片墙。定义网格的方法是:
.grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; }repeat(3, 1fr) 表示平均分成三列,每一列的宽度为 1fr,也就是一份可用空间。Grid 的 1fr 比 Flex 的 flex: 1 更直观,它直接表达“平分轨道空间”。如果你想让第一列固定 250px,第二列自适应,可以写 grid-template-columns: 250px 1fr。
Grid 还有一个常用的高级能力是跨行跨列,通过 grid-column: span 2 让一个单元格横跨两列。用 Grid 搭整体骨架,再用 Flex 处理局部上下左右对齐,这是目前主流的布局组合拳。很多框架的栅格系统底层思路也和 Grid 一致,只是额外加了响应式的断点控制。
3.5 一个卡片组件的完整实现
抛开抽象概念,看一个具体的卡片组件怎么写。假设要做一张个人信息卡片,包含头像、名字、简介和按钮,整体水平排列、在移动端变为上下堆叠。HTML 结构如下:
<div class="card"> <img class="card__avatar" src="avatar.png" alt="头像" /> <div class="card__body"> <h3 class="card__name">某开发者</h3> <p class="card__desc">写了几年前端,喜欢折腾各种小项目。</p> <button class="card__button card__button--primary">关注</button> </div> </div>CSS 这样写:
.card { display: flex; align-items: center; gap: 16px; padding: 16px; border: 1px solid #eee; border-radius: 8px; background: #fff; box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05); } .card__avatar { width: 64px; height: 64px; border-radius: 50%; object-fit: cover; } .card__body { flex: 1; } .card__name { margin: 0 0 4px; font-size: 18px; font-weight: 600; } .card__desc { margin: 0 0 8px; color: #666; line-height: 1.5; } .card__button { padding: 6px 16px; border: none; border-radius: 4px; background: #1677ff; color: #fff; cursor: pointer; } .card__button--primary:hover { background: #0b5fd8; } @media (max-width: 480px) { .card { flex-direction: column; text-align: center; } }细看这段代码,我把 Flex 排列、BEM 命名、盒模型、响应式媒体查询全揉进了一个 30 行的组件里。这就是实际开发中你每天要写的代码形态。关键不在背属性,而在于当你面对“头像和文字要对齐、按钮靠右、底部间距一致”这些需求时,能条件反射地想到用 display: flex 和 gap。
4. 细节决定质量:文本、颜色与视觉
布局决定了页面的大框架,但用户真正感知到的,是文字排印、色彩搭配、圆角阴影这些精致细节。同样的布局,细节处理不同,观感天差地别。一个看起来“高级”的页面,往往不是靠复杂技术,而是靠对文本行高、颜色对比度、留白节奏这些基础属性的细腻把握。
4.1 字体与文本排版
网页排版的核心单位,已经从 px 逐渐让位于相对单位。px 适合边框、阴影这类跟视口无关的固定尺寸,但文本大小如果写成 px,用户调整浏览器字号时,页面毫无反应。我更推荐使用 rem 或 em 作为字号单位。rem 相对于根元素(html)的字号,默认 1rem = 16px,所以常见的做法是给 html 设置 font-size: 62.5%,让 1rem 变成 10px,易于换算。但其实直接用浏览器默认 16px,心里记着“16px = 1rem”的换算关系,也完全够用。
文本细节里最容易忽视的是 line-height(行高)和 letter-spacing(字间距)。中文正文的舒适行高一般在 1.5 到 1.8 之间,数值过小文字挤在一起,过大又显得松散。短标题可以适当增加 letter-spacing 营造一点呼吸感。还有 text-overflow 相关技巧,当文本过长需要省略显示时,必须三件套配合:white-space: nowrap、overflow: hidden、text-overflow: ellipsis。
4.2 颜色与背景
CSS 颜色的写法有很多种:十六进制(#1677ff)、rgb/rgba、hsl。其中 hsl 可能是最被低估的格式,h 表示色相、s 表示饱和度、l 表示亮度,它能让你在保持色相的情况下,快速调节出一个颜色的深浅变体,非常适合做同色系设计。例如主色 hsl(220, 100%, 50%),浅一点就降低饱和度和亮度,深一点就保留色相调整亮度。
rgba 的 alpha 通道则是处理透明度的主力,常用于遮罩层、阴影颜色。背景的完整写法也值得掌握,background 是多个子属性的缩写,可以混合背景图片和渐变。线性渐变的基本写法:
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);这个渐变在早几年算是后台登录页标配,现在依然是一种通用视觉手法。还要记住 currentColor 这个关键词,它表示继承当前元素的 color 值,比如让边框颜色和文字颜色保持一致时,直接 border-color: currentColor,省得写两遍。
4.3 边框、圆角与阴影
border-radius 是让界面“变圆润”的利器。不只是圆形头像需要它,卡片、按钮、输入框,一概用上适度的圆角,视觉上立刻柔和许多。推荐从 4px 到 16px 之间选择,具体取决于组件尺寸和设计语言的风格。
box-shadow 是一个能营造层次感的属性,但很多人写出的阴影脏、重、不自然。它的语法是:box-shadow: 水平偏移 垂直偏移 模糊半径 扩散半径 颜色。一套比较万能的阴影公式是 0 1px 3px 和 0 4px 12px 两层结合使用,一层贴近产生实体感,一层远处产生氛围感。
实际项目中我还喜欢用:hover 时阴影加深、边框变色的微交互。这种 200ms 内的过渡变化,能让页面“活”起来。过渡的写法是 transition: all 0.2s ease,但注意 all 会影响所有属性变化,性能上不如分别罗列需要过渡的属性。
4.4 CSS 变量与主题化
CSS 自定义属性(也叫 CSS 变量)极大提高了样式代码的可维护性。在 :root 选择器里定义全局变量,然后通过 var() 使用:
:root { --color-primary: #1677ff; --color-text: #333; --radius-md: 8px; } .button { background: var(--color-primary); border-radius: var(--radius-md); }变量可以通过覆盖来切换主题。比如想让某个组件局部变成红橙色,直接在它上面重新定义:
.theme-orange { --color-primary: #ff6b35; }因为变量是继承的,.theme-orange 内部调用 var(--color-primary) 的地方都会生效。配合 JavaScript,你可以简单的在 body 上切换>@media (max-width: 768px) { .sidebar { display: none; } }
它的含义是:当视口宽度小于或等于 768px 时,这段规则生效。实际开发中,我习惯从小屏写起,再用 min-width 逐级放大,这叫 Mobile First。这样做有个好处,小屏下的约束多,你先处理最核心的信息,再去大屏上逐步释放空间,加侧栏、加装饰,排版越来越从容。
常见的断点设置,可以参考 480px(小屏手机)、768px(平板竖屏)、1024px(平板横屏或小笔记本)、1280px(桌面端)。但不要死记这组数字,它们只是经验值,更重要的是以你设计的内容在什么宽度下开始“变难看”为准来选断点。
5.2 流动布局与相对单位
媒体查询适合做“断点式”的突变,但页面大部分区域应该保持流畅:宽度随视口变化,而不是一断一断地跳。实现流动布局,核心是善用百分比、vw/vh、fr 这些相对单位。
- 百分比相对父容器宽度,适合定宽的列比例。
- vw、vh 相对于视口宽高,适合做全屏横幅、首屏区块。
- fr 是 Grid 里的份数单位,天然适合等分列。
- clamp() 函数则提供了“区间内弹性变化”的能力,比如 font-size: clamp(14px, 2vw, 20px),表示字号最小 14px、最大 20px,在两者之间随视口宽度平滑变化。这个函数在实现响应式标题时非常实用,免去写多个断点的麻烦。
Flex 的 flex-wrap: wrap 也是响应式里的好朋友。让几个卡片在宽度足够时排成一行,空间不足时自动换行变成多行,几乎不需要媒体查询:
.card-list { display: flex; flex-wrap: wrap; gap: 16px; } .card-list .card { flex: 1 1 240px; }5.3 移动端适配要点
移动端和小屏设备的适配,不仅是尺寸问题,还涉及交互体验。第一个要点是设置 viewport meta 标签,如果没有它,手机浏览器会默认以 980px 的宽度渲染页面,然后缩放给你看,做的一切响应式都白费。HTML 的 head 里必须加上:
<meta name="viewport" content="width=device-width, initial-scale=1.0" />第二个要点是文本可读性。移动端的正文字号不宜小于 14px,行高也要相应放开。不要在小屏上强制让文字填满整个宽度,留出左右边距,信息密度立刻降低。
第三个要点是触控目标大小。移动端的点击目标(按钮、链接)最好不小于 44px x 44px,这是 Keep 住手指误触的基本尺度。同时记得给按钮的 hover 效果提供移动端替代,因为手机上根本没有 hover,要改用 active 状态。
6. 浏览器调试与常见问题排查
写了 CSS 不等于样式对,最终以浏览器渲染为准。不夸张的说,排查样式问题占据了前端日常开发相当可观的时间比例。好在我们有浏览器开发者工具这样的利器。与其瞎猜乱试,不如掌握一套系统的排查方法,几分钟就能定位问题所在。
6.1 用 DevTools 排查样式不生效
打开浏览器开发者工具(快捷键 F12 或右键检查),选择 Elements 面板,点击页面中的元素,右侧 Styles 栏会列出所有命中该元素的选择器和对应的样式声明。上方往往还有一行“继承自某某元素”的提示,能帮你理清样式来源。
遇到样式不生效时,我推荐按这个顺序排查:
- 规则是否被“删除线”划掉:这代表该样式被其他同优先级或更高优先级的规则覆盖,此时看一下是哪个选择器、哪个属性压过了你的声明。
- 选择器到底匹配到没有:如果 Styles 栏里根本没有你的类名,说明选择器写错了,或者类名与 HTML 不对应。
- CSS 文件是否正常加载:切到 Network 面板看 CSS 请求状态,404 说明路径错了;如果文件加载正常,检查是否有语法错误,Console 面板通常会有提示。
- 是否被浏览器默认样式影响:很多“为什么我的 h1 特别大”的问题,根源就是默认样式。先在自己的样式表里做 reset,再调试。
我尤其喜欢 DevTools 里的“强制激活伪类”功能,可以在 Elements 面板里模拟 :hover、:focus 状态,不用真去碰鼠标,调试交互样式特别方便。Computed 面板则会展示该元素所有计算后的实际值,能帮你一眼看出 margin 塌陷、盒模型溢出等实际问题。
6.2 经典布局问题与解法
整理几个几乎所有人都会遇到的经典布局问题,以及对应解法。
第一个是垂直居中。老办法是绝对定位加负 margin,现在 Flex 三行代码搞定:父容器 display: flex,子元素 margin: auto,或者直接在父容器设置 align-items: center 和 justify-content: center。Grid 也能做,display: grid 加 place-items: center 就完事。
第二个是 margin 塌陷。父容器和子元素的 margin 有时会合并成一个最大的 margin,导致子元素的 margin-top 看起来没生效,反而把父容器“推”下来了。解决办法之一是在父容器加 overflow: hidden(触发 BFC),或者改用 padding 代替 margin,或者用 flex/grid 容器(它们内部的结构天然避免了这个坑)。
第三个是图片底部出现空隙。默认图片是行内元素,行内元素的垂直对齐与基线(baseline)有关,底部会留出一点间隔。给图片设置 display: block 或者 vertical-align: middle 就能解决。
第四个是 z-index 不生效。z-index 只对设置了 position(非 static)或 flex/grid 子项的元素生效。如果两个元素在同一个层叠上下文里,z-index 数值大者在上;但如果是不同的层叠上下文,它们父级的 z-index 才是决定性因素。所以排查时先看有没有定位属性,再看曾经的祖先有没有创建层叠上下文。
6.3 性能与规范建议
最后聊聊让 CSS 长期可维护的几条实战经验。第一,选择器性能不必过度纠结,但别写那种逐层限定的大长串,比如 html body div ul li a,它既不快也不易读。尽量控制在三层以内,能用类直接点到就不加多余的后代钩子。
第二,避免滥用 !important。它虽然能快速覆盖其他样式,但让整个层叠体系失去控制。如果发现一个样式必须靠 !important 才能生效,通常说明前面的优先级设计出了问题,先去简化选择器或调整结构。
第三,建议给项目一份规范化的 reset 文件,把默认 margin、padding、box-sizing、字体等统一处理,然后组织文件时按“基础样式 + 组件样式 + 页面样式”分层,这种结构在多人协作时尤其重要。
第四,命名规范从第一天开始就立好。哪怕只是自己写练习项目,也尽量使用语义化、组件化的命名,不要出现 .div1、.red-text 这种没有信息量的名字。类名是代码的一部分,别人读你的 CSS,其实就是读你的思路。
我在实际带人的过程中发现,CSS 学得最透的同学,并不是背属性最多的,而是早早理解了盒模型、文档流、优先级这套底层逻辑的人。只要这三样立住了,后面碰到 Flex、Grid、响应式,都是顺着逻辑长出来的能力,不需要死记硬背。最后送各位一个小技巧:遇到想不明白的样式问题,先别急着在编辑器里乱加属性,打开 DevTools,看 Computed 面板里实际的值,问题多半自己就现出原形了。CSS 学习路上没有捷径,但有了这套方法论,至少能少走我当年走过的那些弯路。