css 预处理、PostCSS、LightingCSS

最后修改于

改进 CSS 的方案有很多,除了 CSS 本身的书写范式外,还有一种思路,类似于 JS 的 babel / webpack 等一系列工具链,在 CSS 的上下游对其进行修改。通过各种 pre/post 处理器来实现各种fancy 的特性。

  • 预处理器通常是作为 CSS 方言,为 CSS 提供一些可编程特性,提高代码复用能力。
  • 后置处理器,则是对 CSS 进行处理,通过静态分析,来为已有的 CSS 进行补足,比如兼容性问题,移除冗余、代码拆分等。

Scss#

Scss 是一种 CSS 方言,最早出现于 2006 年,为 CSS 引入了可编程特性,从而实现 CSS 规则的复用,直到现在,SCSS 的采用率也非常高,与各种 CSS 范式配合得很好。

变量#

如同其他编程语言一样,变量提供了最基本的值的复用,可以存储所有 CSS 值,以 $ 符号开头的内容被视为变量,引用的方式也是类似的。

// input
$font-stack: Helvetica, sans-serif;
$primary-color: #333;
body {
  font: 100% $font-stack;
  color: $primary-color;
}
// output
body {
  font: 100% Helvetica, sans-serif;
  color: #333;
}
嵌套规则#

HTML 本身具有清晰层次结构,但作为 HTML 的样式工具,CSS 却没有。
Sass 为 CSS 引入嵌套语法,从而得到更符合心智的 CSS 书写体验

// input
nav {
  ul {
    margin: 0;
    padding: 0;
    list-style: none;
  }

  li { display: inline-block; }

  a {
    display: block;
    padding: 6px 12px;
    text-decoration: none;
  }
}
// output
nav ul {
  margin: 0;
  padding: 0;
  list-style: none;
}
nav li {
  display: inline-block;
}
nav a {
  display: block;
  padding: 6px 12px;
  text-decoration: none;
}

SCSS

  1. 变量引用
  2. 嵌套规则展平 (默认后代),父类选择 &
    群组嵌套处理 matrix)
  3. > ~ + 子类,邻居,同层选择
  4. 属性嵌套,css 属性名拆分,缩写
  5. 导入 @import (sass 导入和原生 css 导入)
  6. 局部 sass 文件 (不编译成最终 css 文件)
  7. 嵌套导入
  8. !default 规则
  9. 混合 @mixin (本质是函数,在其他位置通过 @include 进行引用),支持无参,匿名参,具名参,默认参
  10. @extend,继承 css 规则,将规则 A 的所有关联规则继承
  11. 关联继承的占位符选择器 %,只用于 extend (类似于 abstract class)
  12. script 运算 +-*/
    颜色 hex 运算,字符串连接,功能函数
  13. 插值 #{variable}
    13. 控制指令 @if,@for,@each
  14. 高级函数 @function
混入@mixin#
// input
@mixin horizontal-list {
  li {
    display: inline-block;
    margin: {
      left: -2px;
      right: 2em;
    }
  }
}

nav ul {
  @include horizontal-list;
}
// output
nav ul li {
  display: inline-block;
  margin-left: -2px;
  margin-right: 2em;
}

混入本身可视为一种函数,通过@mixin定义,随后通过@include引用。提供了一种样式复用的能力。主要缺点在于,mixinCSS代码的复制粘贴,这会导致 CSS 中包含大量的冗余内容。

继承#

类似于混入,同样是一种复用功能,区别在于继承不是代码的复制粘贴。而是在所有的 "被继承选择器"(下面为.error)出现的地方,都新增一个执行继承操作的选择器.error-serious

// input
.error {
  gap: 2;
}
a .error {
  border: 1px #f00;
  background-color: #fdd;

  &--serious {
    @extend .error;
    border-width: 3px;
  }
}
// 拆分
.error {
	gap: 2;
}
a .error {
  border: 1px #f00;
  background-color: #fdd;
}
a .error--serious {
	@extend .error;
}
a .error--serious {
	border-width: 3px;
}
// output
.error, a .error--serious {
  gap: 2;
}
a .error, a .error--serious {
  border: 1px #f00;
  background-color: #fdd;
}
.error--serious {
  border-width: 3px;
}
模块化导入 @import#

@import 与 css 标准的 import 类似,以下划线_开头的文件只用于导入,不会生成最终的 css 文件

高级控制#

if for while function return 插值

Less#

类似于 Scss,相对而言,语法很多与 css 原生语法冲突,比如变量用 @,命名空间用 #,混入直接加在选择器上()(这样的隐式声明会使得难以分辨一个选择器本身是否被作为混入调用)

PostCSS/LightningCSS#

PostCSS / LightningCSS 与预处理器在优化 CSS 这件事上走的是完全不同的道路。通过对已有的 CSS 进行静态分析,对其进行补足。这两者的作用都是提供对 CSS 上下游进行操作的便捷能力(如静态分析、转换、打包),提供了一些基本的增强,如 CSS 转义,更多功能也可以由插件系统来完成。
PostCSS --- PostCSS Architecture

Mermaid Loading...

此处仅罗列一下常用的 CSS 转换工具,更多可参阅PostCSS Plugins

  • AutoPrefixer,Post CSS 插件,为 CSS 添加浏览器前缀提高兼容性。
  • postcss-preset-env,将现代 / 实验性 CSS 特性转义为兼容性更高的表达方式。
  • cssnano,压缩 CSS,优化 CSS 大小。

Lightning CSS本身是通过 Rust 开发的,在性能上有更高的上限。相比于 PostCSS 是纯粹的 CSS 转换器,还自带了一系列现代 CSS 开发中所需要的特性(如 CSS module、 最小化打包 CSS、浏览器适配)。