为什么 CSS 会自己学着长大(变臃肿)呢???🐶 🐶 🐶
概述
实际开发中,不管是自己单兵作战,还是多人协作,时间一久,代码体积总会呈 「弱指数」 的走势增长,很是头疼。
一些原因
简单总结,大致有以下几类不好的习惯:
1、不利用简写
不利用语言本身的简写特性,编写冗余代码。
举个例子:
/* bad */
h2 {
padding-top: 1px;
padding-right: 2px;
padding-bottom: 2px;
padding-left: 2px;
}
/* good */
h2 {
padding: 1px 2px 2px 2px;
}
当然,只超过单个同类属性,就可以简写,不一定四个的时候才简写:
/* bad */
h2 {
padding-top: 1px;
padding-left: 2px;
}
/* good */
h2 {
padding: 1px 0 0 2px;
}
需要注意的是,补齐其他的默认值的时候,需要了解该属性的默认值是什么。
当然,简写,除了属性的简写,还有值本身的简写:
/* 颜色 */
/* bad */
.c-white {
color: #ffffff;
}
/* good */
.c-white {
color: #fff;
}
/* 单位 */
/* bad */
.w-0 {
width: 0px;
}
/* good */
.w-0 {
width: 0;
}
2、过度嵌套
受现代预编译器(sass
less
stylus
等)的影响,不管是你,还是你的同事,都很容易写出下面的代码:
.main {
color: red;
.content {
margin-left: 2px;
.side {
position: absolute;
ul {
margin-left: 10px;
li {
background-color: tomato;
span {
font-size: 14px;
&:before {
content: "";
}
}
}
}
}
}
}
- 然后,新需求改一下,会引发未知的影响。
- 你改不动别人的。
- 别人改不动你的。
- (来啊,互相伤害啊,啊啊啊)
- 就疯狂使用高优先的来覆盖,
id
inline-style
,更有甚者,!important
- 然后,就是另一个故事了…
当然,过度嵌套的难以维护只是一方面,这种结构会让 css
变得像老太婆的裹脚布。诸位有没有想过,上面的例子,编译成最终的 css,会是什么样?
.main {
color: red;
}
.main .content {
margin-left: 2px;
}
.main .content .side {
position: absolute;
}
.main .content .side ul {
margin-left: 10px;
}
.main .content .side ul li {
background-color: tomato;
}
.main .content .side ul li span {
font-size: 14px;
}
.main .content .side ul li span:before {
content: "";
}
倒不是说最后编译的代码量多,稍微了解 css渲染
的同学都知道,浏览器对 css选择器
的解析规则是从右向左,所以前面写在多也起不了什么作用,只会增加查找成本。一般建议的是层级保持在3层以内,最多不超过4层。
同时也不建议裸写纯 tag
,而是都带上语义化的 class
,至于为啥,聪明的你应该一眼能看出来。
3、无用的修饰属性
这个是什么意思呢?
看下面这段代码:
display: block;
vertical-align: middle;
display: inline;
width: 100px;
height: 40px;
margin: 10px;
有看出啥问题吗?
看看在 vscode(设置过规则)
中的表现吧
是的,当设置了某个属性的时候,有部分属性设置是无效的,这一类的问题,可以使用一系列的 css.lint
来规避掉。
4、不利用语言继承特性
这个其实跟第一点一样,都是没有利用好语言特性。
你一定见过这样的代码:
.wrapper span {
font-size: 14px;
}
.wrapper p {
font-size: 14px;
}
.wrapper h1 {
font-size: 14px;
}
其实,完全可以只设置顶层/父元素的字号属性即可:
.wrapper {
font-size: 14px;
}
因为 font-size
属性是可以继承的。
更多的可继承性,移步笔者的另一篇文章:《CSS中属性的可继承性》
5、臃肿的库
你肯定用过诸如 Bootstrap
的样式库,再前沿一些,也可能用过 Bulma
、 Tailwind
等,不可否认,使用封装好的样式库,在实现视觉效果上,确实很便捷。
但是,为了其中某个效果,而引进整个库,未免会有些不合适,尤其是 Tailwind
,其大小达到了 485KB,显然是不能接受的。
这个问题怎么解,下面会解决。
优化建议
自然地,从上面的一些原因,已经蹦出好几条优化 css
的建议。
常规
- 利用简写
- 不要过度嵌套
- 避免无用的修饰属性
- 利用继承特性
当然,常见的这几条,是在日常编码中的建议,为了瘦身,也为了增强可读性。
至于上面提到的第五点,最直观的想法是,剔除没用到的,只保留用到的,类似 rollup
针对 es6
的 tree shaking
。
那在 css
中,剔除多余代码,应该怎么做呢?
方式有很多,这里只介绍 PurgeCSS
。
PurgeCSS
PurgeCSS 是一个通过字符串对比,来决定移除不需要的 CSS 的工具。
其原理其实通过上面的一句话,就能完全知道。不过里边有一些细节,以及会「误伤」实际需要的样式(比如 js
拼接的 className
),该怎么处理,大家可以去官网自己了解。
有个数据,常规使用 Tailwind
的项目,使用 PurgeCSS
前后对比是:
- 不启用
PurgeCSS
,tailwind.css
485 KB - 启用了
PurgeCSS
,tailwind.css
16 KB
以上。