CSS工程化
工程化的意义
在最原始的开发阶段大家都是手写原生的 CSS,但原生 CSS 存在着诸多问题。例如:
- 不支持选择器的嵌套
.container .header .nav .title .text {
color: blue;
}
- 样式污染问题。如果出现同样的类名,很容易造成不同的样式互相覆盖和污染。
/* a.css */
.container {
color: red;
}
/* b.css */
/* 会覆盖 a.css 的样式! */
.container {
color: blue;
}
- 浏览器兼容问题。为了兼容不同的浏览器,我们需要对一些属性(如 transition )加上不同的浏览器前缀,比如 -webkit-、-moz-、-ms-、-o-,意味着开发者要针对同一个样式属性写很多的冗余代码。
- 打包后的代码体积问题。如果不用任何的 CSS 工程化方案,所有的 CSS 代码都将打包到产物中,即使有部分样式并没有在代码中使用,导致产物体积过大。
现代 CSS 工程化方案
CSS 语言在过去若干年中一直在追求样式表现力方面的提升,工程化能力薄弱,例如缺乏成熟的模块化机制(不像 JS 拥有 import)、依赖处理能力、逻辑判断能力等。
所以 CSS 工程化基本都是要依赖第三方来实现。
CSS 预处理器
为了能解决 CSS 选择器嵌套并能将 CSS 赋予了动态语言的特性,如变量,继承,运算, 函数等功能。现代 CSS 工程化中出现了 CSS 预处理。
主流 CSS 预处理器有以下三个:
- Sass/Scss
- Less
- Stylus
例如 scss 嵌套:
.test {
.font {
font-size: 10px
}
}
这三个主流预处理器功能基本差不多,只是一些写法会有不同。根据自己的喜好来选中即可。
TIP
注意 CSS 预处理器只是将我们编写的 CSS 代码处理成浏览器支持的 CSS 代码,并不是浏览器能支持 CSS 选择器嵌套等功能。
CSS Modules(CSS 模块化)
Css Modules 是通过对标签类名进行加装成一个独一无二的类名,这样就可以避免同名的情况下样式污染的问题。
基本上 CSS Modules 都会被集成到架构工具里面。例如 Webpack 的 css-loader。
例如:转化前
.name {
font-size: 12px
}
转化后
.name_xxxxx {
font-size: 12px
}
TIP
scoped 是 vue-loader 带来的模块方案,使用 CSS 后处理器 PostCSS 来实现 Scoped CSS。原理就是给声明了scoped的样式中选择器命中的元素添加一个自定义属性,再通过属性选择器实现作用域隔离样式的效果。
CSS 后处理器
CSS 后处理器是对 CSS 进行处理,并最终生成 CSS 的预处理器。
例如用来 PostCSS 解析和处理 CSS 代码,可以实现的功能非常丰富,比如将 px 转换为 rem、根据目标浏览器情况自动加上类似于--moz--、-o-的属性前缀等等。
例如浏览器兼容:转化前
:fullscreen {
}
转化后
:-webkit-full-screen {
}
:-ms-fullscreen {
}
:fullscreen {
}
CSS In JS
简单来说 CSS-in-JS 就是将应用的 CSS 样式写在 JavaScript 文件里面,而不是独立为一些 .css,.scss 或者 less 之类的文件,这样你就可以在CSS中使用一些属于JS的诸如模块声明,变量定义,函数调用和条件判断等语言特性来提供灵活的可扩展的样式定义。主流的包括 emotion、styled-components 等等。
CSS 原子化框架
如Tailwind CSS、Windi CSS,通过类名来指定样式,大大简化了样式写法,提高了样式开发的效率,主要解决了原生 CSS 开发体验的问题。
例如 Windi CSS 的设置 padding 和文字居中:
<div className="p-20px text-center" />
TIP
针对不同的问题,现代 CSS 工程化拥有不同的解决方案,并不存在谁高谁低的问题。实际使用情况请根据自己的爱好和项目需求来。