我理解的postcss(现代CSS语法转为旧版语法)

227 阅读2分钟

1. 核心原理

  1. 目标浏览器版本:根据 .browserslistrc 中定义的浏览器范围(如 last 2 versions)。
  2. 兼容性数据查询:从 caniuse 获取 gap 属性的浏览器支持情况。
  3. 语法降级规则:发现旧版浏览器(如 Edge 16)不支持 gap 但支持 grid-gap,则触发转换。

2. 具体流程(以 gap 为例)

步骤 1:查询浏览器支持数据

  • 通过 caniuse 数据可知:
    • gapEdge 16 中需要前缀 -ms-grid-gap
    • gapSafari 13.1 中无需前缀,但需配合 display: grid

步骤 2:根据目标浏览器生成代码

假设 .browserslistrc 配置包含旧版 Edge:

> 0.5%, last 2 versions, Edge 16

工具链(如 Autoprefixer)会执行以下转换:

/* 原始代码 */
.container {
  display: grid;
  gap: 20px;
}

/* 转换后代码 */
.container {
  display: -ms-grid;
  display: grid;
  -ms-grid-gap: 20px;  /* Edge 16 需要的旧语法 */
  grid-gap: 20px;       /* 旧版标准语法 */
  gap: 20px;            /* 现代标准语法 */
}

3. 工具如何知道“怎么改”?

底层规则库

  • Autoprefixer 和 postcss-preset-env 内置了 CSS 属性转换规则,例如:
    // Autoprefixer 内部规则片段
    {
      prop: 'gap',
      browsers: ['Edge <= 16'],
      replace: {
        value: '-ms-grid-${value}',
        prop: 'grid-gap'
      }
    }
    
  • 这些规则库的更新与 caniuse 数据保持同步。

验证方法

  • 手动查询:caniuse.com 直接搜索属性
  • 工程验证:在目标浏览器中运行测试用例

4. 理解修正

实际情况
动态规则:根据浏览器支持数据实时判断
渐进增强:同时保留新旧语法

5. 自定义转换规则(高级)

你甚至可以扩展 PostCSS 规则:

// postcss.config.js
module.exports = {
  plugins: [
    require('autoprefixer'),
    require('postcss-flexbugs-fixes'),
    // 自定义规则:将 `gap` 转换为 `margin`
    (root) => {
      root.walkDecls('gap', decl => {
        decl.cloneBefore({ prop: 'margin', value: decl.value });
      });
    }
  ]
}
/* 输入 */
.container { gap: 20px; }

/* 输出 */
.container { 
  margin: 20px; /* 自定义规则添加 */ 
  gap: 20px; 
}