You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ESBuild与PostCSS编译CSS自动加斜杠引发语法警告求助

CSS :has选择器在ESBuild+PostCSS构建中被转义导致语法警告的根本解决办法

问题描述

使用ESBuild结合PostCSS构建项目,引入CSS :has 选择器后,编译阶段出现CSS语法警告,生成的CSS代码中:has被自动转义为\:has,同时后续的括号、属性选择器内容也被错误转义,导致括号匹配异常。测试将postcss-preset-env的stage设为3时警告消失,需知晓根本解决办法。

控制台日志

▲ [WARNING] Expected "]" to go with "[" [css-syntax-error]

    postcss:/home/encompass/Projects/SNAP/LOCAL/pp_alue/app/public/wp-content/themes/ppshp-modular-theme/src/assets/styles/style.pcss:9561:36:
      9561 │ .language-switcher-container[\:has\(.language-switcher-selected\[aria-expanded\%3D\%22true\%2...
           │                                     ^
           ╵                                     ]

  The unbalanced "[" is here:

    postcss:/home/encompass/Projects/SNAP/LOCAL/pp_alue/app/public/wp-content/themes/ppshp-modular-theme/src/assets/styles/style.pcss:9561:28:
      9561 │ .language-switcher-container[\:has\(.language-switcher-selected\[aria-expanded\%3D\%22true\%2...
           ╵                             ^

▲ [WARNING] Unexpected "]" [css-syntax-error]

    postcss:/home/encompass/Projects/SNAP/LOCAL/pp_alue/app/public/wp-content/themes/ppshp-modular-theme/src/assets/styles/style.pcss:9561:98:
      9561 │ ...e-switcher-container[\:has\(.language-switcher-selected\[aria-expanded\%3D\%22true\%22\]\)] {
           ╵                                        

问题输出示例

.language-switcher-container[\:has\(.language-switcher-selected\[aria-expanded\%3D\%22true\%22\]\)] {
  background-color: var(--colors-primary-blue-10);
  border-radius: 4px 4px 0 0;
}
.language-switcher-container:has(.language-switcher-selected[aria-expanded="true"]) {
  background-color: var(--colors-primary-blue-10);
  border-radius: 4px 4px 0 0;
}

构建配置

const stylesPlugin = [
  postCssPlugin({
    plugins: [
      postCssPresetEnv({ stage: 1}),
      postCssEasyImport({ extensions: ['.css', '.pcss'] }),
      postCssExtendRule,
      postCssReporter(),
      url({ url: 'inline' })
    ],
  }),
];

const lint = async () => {
  try {
    const eslint = new ESLint();
    const results = await eslint.lintFiles(['src/**/*.js']);

    const formatter = await eslint.loadFormatter('stylish');
    const resultText = formatter.format(results);

    console.log(resultText);
  } catch (err) {
    console.error(err);
  }
};

const buildScripts = async () => {
  console.log('Building scripts ...');

  try {
    const timerStart = Date.now();

    // Build code
    await esbuild.build({
      entryPoints: [
        'src/endpoints/scripts.js',
        'src/endpoints/scripts.admin.js',
      ],
      format: 'iife',
      bundle: true,
      minify: true,
      outdir: 'dist/',
      plugins: [...stylesPlugin],
      sourcemap: true,
      external: ['*.svg', '*.woff', '*.css', '*.jpg', '*.png'],
    });

    const timerEnd = Date.now();
    console.log(`Done! Scripts built in ${timerEnd - timerStart} ms.`);
  } catch (error) {
    console.log(error);
  }
};

根本原因

postcss-preset-env的stage参数控制CSS特性的支持级别:

  • 当stage:1时,:has选择器仍处于实验性阶段,插件会将其视为非标准语法,自动进行转义处理,错误地转义了:has及后续的括号、属性选择器内容,导致语法结构混乱。
  • 当stage:3时,:has已被纳入候选标准,插件不再对其进行转义,因此警告消失。

解决办法

1. 显式启用:has选择器支持(推荐)

无需调整stage全局级别,直接在postcss-preset-env配置中指定启用css-has-pseudo特性,精准控制单个特性的处理逻辑:

postCssPresetEnv({
  stage: 1,
  features: {
    'css-has-pseudo': true
  }
})

2. 调整postcss-preset-env的stage为3

将stage设为3,此时:has被视为稳定特性,插件不会对其进行转义。但需注意,stage升级会影响其他CSS特性的处理逻辑,需确认项目对更高stage特性的兼容性:

postCssPresetEnv({ stage: 3 })

3. 确认PostCSS插件顺序

确保postcss-preset-env在所有处理选择器的插件之前执行,避免其他插件干扰转义逻辑。当前配置中postcss-preset-env已处于第一个位置,符合要求。

验证说明

修改配置后重新执行构建,检查:

  • 控制台无CSS语法警告输出
  • 生成的CSS代码中保留原始的:has(.language-switcher-selected[aria-expanded="true"])语法,无不必要的转义字符

内容的提问来源于stack exchange,提问作者Encompass

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 05:10:21