英文 | https://medium.com/better-programming/10-best-practices-for-improving-your-css-84c69aac66e。CSS 看起来很难写错:加几条规则就能改外观。小站点几个文件确实如此;大应用里样式会迅速失控。如何让它可管理?
和其他语言一样,CSS 能成全也能毁掉设计。下面 10 条实践,帮你从样式里拿到最大收益。
| 序号 |
做法 |
收益 |
| 1 |
先问要不要框架 |
少带用不到的选择器 |
| 2 |
BEM / ITCSS / OOCSS |
命名和分层一致 |
| 3 |
预处理器 + 后处理器 |
拆文件、前缀、变量 |
| 4–7 |
语义标签、简写、去冗余、简单选择器 |
更小更快更好改 |
| 8–10 |
保留 :focus 轮廓、移动优先、压缩 |
可访问、少覆盖、体积小 |
一、你真的需要一个框架吗?
先确定要不要 CSS 框架。现在有不少轻量替代。通常你不会用到框架里每个选择器,包里就会有无效代码。
如果只用按钮样式,把那部分拷进自己的 CSS,删掉其余。也可以用 DevTools 的代码覆盖率找未使用规则。

在工具面板搜 Coverage,或 Ctrl+Shift+P 打开工具面板。点重新加载开始录制。红色表示未使用。上例显示 98% CSS 未使用——其实不完全是:有的样式要交互后才用,移动端样式也会标成未使用。删之前务必确认真没用。
二、首选一套 CSS 方法
方法是为了文件里的一致性,方便扩展和维护。
BEM
Block、Element、Modifier,最流行的命名之一,方便做可复用组件:
.block { ... }.block__element { ... }.block--modifier { ... }
-
-
.block__element:块的一部分,必须绑在块上。
-
.block--modifier:外观、行为或状态标志,例如 .block--hidden。
ITCSS
倒三角 CSS:一层层加特性,越往下越具体。

OOCSS
分离结构和皮肤:视觉效果不要和结构写死在一起。
/* Instead of */
.box {
width: 250px;
height: 250px;
padding: 10px;
border: 1px solid #CCC;
box-shadow: 1px 2px 5px #CCC;
border-radius: 5px;
}
/* Do */
.box {
width: 250px;
height: 250px;
padding: 10px;
}
.elevated {
border: 1px solid #CCC;
box-shadow: 1px 2px 5px #CCC;
border-radius: 5px;
}
分隔容器和内容:元素不要依赖所在位置,同一元素在哪都应长一样。
/* Instead */
.main span.breadcumb { ... }
/* Do */
.breadcrumb { ... }
三、设置预处理器
预处理器提供 CSS 没有的高级能力:循环、变量、函数。常见是 Sass、Less、Stylus。建议 Sass:社区和文档都多。
可以把文件拆成可复用的小文件,互相 import,或分别引进应用:
// Import different modules into one SCSS file
@import 'settings';
@import 'tools';
@import 'generic';
@import 'elements';
@import 'objects';
@import 'components';
@import 'trumps';
嵌套选择器
CSS 本身缺的简单能力,嵌套能看清结构:
.wrapper {
.sidebar {
&.collapsed {
display: none;
}
.list {
.list-item {
...
&.list-item--active {
...
}
}
}
}
}
自动加浏览器前缀
实验性特性要加前缀:-webkit-(Chrome/Safari/新 Opera)、-moz-(Firefox)、-o-(旧 Opera)、-ms-(IE/Edge)。支持主流浏览器就要写多遍:
.gradient {
background: rgb(30,87,153);
background: -moz-linear-gradient(top, rgba(30,87,153,1) 0%, rgba(41,137,216,1) 50%, rgba(32,124,202,1) 51%, rgba(125,185,232,1) 100%);
background: -webkit-linear-gradient(top, rgba(30,87,153,1) 0%, rgba(41,137,216,1) 50%, rgba(32,124,202,1) 51%, rgba(125,185,232,1) 100%);
background: linear-gradient(to bottom, rgba(30,87,153,1) 0%, rgba(41,137,216,1) 50%, rgba(32,124,202,1) 51%, rgba(125,185,232,1) 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#1e5799', endColorstr='#7db9e8', GradientType=0);}
mixin 可以当函数用,避免硬编码重复:
@mixin gradient() {
background: rgb(30,87,153);
background: -moz-linear-gradient(top, rgba(30,87,153,1) 0%, rgba(41,137,216,1) 50%, rgba(32,124,202,1) 51%, rgba(125,185,232,1) 100%);
background: -webkit-linear-gradient(top, rgba(30,87,153,1) 0%, rgba(41,137,216,1) 50%,rgba(32,124,202,1) 51%, rgba(125,185,232,1) 100%);
background: linear-gradient(to bottom, rgba(30,87,153,1) 0%, rgba(41,137,216,1) 50%,rgba(32,124,202,1) 51%, rgba(125,185,232,1) 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#1e5799', endColorstr='#7db9e8', GradientType=0);}
.gradient {
@include gradient();
}
后处理器
预处理器生成 CSS 后,后处理器再优化。常见是 PostCSS:按 Can I Use 自动加前缀。autoprefixer 甚至不用手写前缀,例如支持最近四个版本:
const autoprefixer = require('autoprefixer')({
browsers: [ 'last 4 versions', 'not ie < 9' ]
});
用变量做一致设计
变量和 mixin 一起,能把设计规则固化:
// Font definitions
$font-12: 12px;
$font-21: 21px;// Color definitions
$color-white: #FAFAFA;
$color-black: #212121;
四、能用标记就别堆 CSS
选对 HTML 元素就能减小 CSS。标题如果写成:
span.heading {
display: block;
font-size: 1.2em;
margin-top: 1em;
margin-bottom: 1em;
}
用 span 当标题就要覆盖 display、间距、字体。换成 h1/h2/h3,默认样式已经够用,四条规则可以立刻丢掉。
五、使用速记属性
上面的 margin 可以写成:
.heading { margin: 1em 0;}
padding、border、background 同样适用。
六、减少冗余
两个类只差一两规则时,抽出公共部分当额外类。不要这样:
<style>
.warning {
width: 100%;
height: 50px;
background: yellow;
border-radius: 5px;
}
.elevated-warning {
width: 100%;
height: 50px;
font-size: 150%;
background: yellow;
box-shadow: 1px 2px 5px #CCC;
border-radius: 5px;
}
</style>
<div class="warning">⚠️</div><div class="elevated-warning"></div>
改成:
<style> .warning {
width: 100%;
height: 50px;
background: yellow;
border-radius: 5px;
}
.warning--elevated {
font-size: 150%;
box-shadow: 1px 2px 5px #CCC;
}
</style>
<div class="warning">⚠️</div><div class="warning warning--elevated"></div>
七、避免复杂选择器
复杂选择器有两害:特异性高,以后更难覆盖;浏览器匹配也更慢。
匹配选择器
浏览器从右到左解释选择器,这比反过来快。例如:
.deeply .nested .selector span { ...}
先匹配所有 span,再过滤 .selector,依此类推。不建议用标签做选择器,因为它会碰上每个该标签。单次可能只有零点几毫秒,但养成降低复杂度是好习惯。
让人也能读懂
机器难解析,人也难。下面这条何时生效?
[type="checkbox"]:checked + [class$="-confirmation"]::after { ...}
用自定义类加 JS 切换会简单得多:
.confirmation-icon::after { ...}
真的别无选择时,至少写清注释:
/** * Creates a confirmation icon after a checkbox is selected. * Select all labels ending with a class name of "-confirmation" * that are preceeded by a checked checkbox. * PS.: There's no other way to get around this, don't try to fix it. **/
.checkbox:checked + label[class$="-confirmation"]::after { ...}
八、不要删除轮廓
最常见错误之一:觉得去掉 :focus 高亮没事,其实让键盘用户找不到焦点。常被写进 reset:
:focus { outline: none;}
只用键盘导航的人就不知道自己在哪。默认样式不合品牌就做自定义轮廓,但必须有焦点指示。
九、首先使用移动设备
媒体查询请移动优先:先写小屏,再往上加,也叫渐进增强。这样是给大屏加规则,而不是覆盖已有 CSS,最终规则更少。判断方法:查询用 min-width 就走对了。
/* Mobile-first media query, everything above 600px will get the below styles */
@media (min-width: 600px) { /* your CSS rules */}
/* Non mobile-first media query, everything below 600px will get the below styles */@media (max-width: 600px) { /* your CSS rules */}
十、压缩
压缩捆绑文件:去掉注释和空白。服务器端也要开压缩。还可以混淆类名进一步减小 CSS 和标记。
-
-
Gulp:gulp-minify-cssnames
-
这 10 步能让 CSS 更轻、更好维护、更好扩展。预定义调色板和版式规则也会让设计更一致、样式更可复用。原文
一句话总结:大项目里 CSS 要靠方法(BEM/ITCSS)和工程化(预处理器、覆盖率、压缩)管住体积与特异性,而不是堆选择器。