不能直接用 CSS.supports('--color'),因为该方法只接受完整属性值对(如 'color', 'var(--primary)'),不支持仅传入自定义属性名,且 IE11 等旧环境根本未实现该 API,会抛 TypeError。
CSS.supports('--color')
IE11 和部分旧版 WebView(如 Android 4.4 系统 WebView)会直接抛出 TypeError: CSS.supports is not a function,因为 CSS.supports 在这些环境里根本不存在。更隐蔽的坑是:即使你加了 typeof CSS.supports === 'function' 判断,传入 '--color' 这种只带自定义属性名的字符串,在 IE11 里仍会报错——它只接受完整声明对,比如 'color', 'var(--primary)'。
常见错误写法:
CSS.supports('--primary') → IE11 崩溃CSS.supports('display: grid') → 缺少第二个参数,Chrome 也会返回 false(语法错误)正确调用必须是两参数形式,且值部分得是合法 CSS 值字符串:
if (CSS.supports('display', 'grid') && CSS.supports('gap', '1rem')) { document.body.classList.add('supports-grid-gap');}
@ant-design/cssinjs 的 StyleProvider 怎么配合 CSS.supports
Ant Design 5.x 默认启用 :where 和逻辑属性(margin-inline-start),但它们在 IE11、360 极速模式、QQ 浏览器 X5 内核下全都不认。你不能指望 StyleProvider 自动检测并切换——它本身不执行运行时特性检测,只是按配置静态输出样式。
立即学习“前端免费学习笔记(深入)”;
要实现「自动降级」,得手动组合两步:
CSS.supports 检测关键能力(如 'display', 'grid'、'margin-inline-start', '1rem'),然后给 <html> 或 <body> 加 classStyleProvider 外层包裹条件逻辑,传入不同 transformer 配置示例(React + TypeScript):
const supportsModernCSS = CSS.supports('display', 'grid') && CSS.supports('margin-inline-start', '1rem');export default () => ( <StyleProvider transformers={ supportsModernCSS ? [] : [legacyLogicalPropertiesTransformer] } hashPriority={supportsModernCSS ? 'low' : 'high'} > <MyApp /> </StyleProvider>);
注意:hashPriority="high" 会移除 :where,但也会让样式优先级变高,可能和用户自定义样式冲突,需同步检查全局选择器权重。
CSS.supports 会失效,怎么办服务端(Node.js)没有 CSS 对象,CSS.supports() 直接 undefined。如果首屏渲染依赖这个判断,客户端水合时 class 名或 transformer 配置不一致,就会触发 React 的 mismatch warning,甚至样式闪动。
可靠解法只有两个:
/Trident|MSIE|Edge/1[0-8]/.test(navigator.userAgent)),虽然不准但 SSR 可执行;<html class="no-cssvars no-grid"> 硬编码进 HTML 模板,JS 只负责在支持时 removeClass,避免首次渲染差异。别用 useEffect 动态加 class——首屏内容已渲染完成,再切 class 会导致重绘,尤其含动画的组件会跳帧。
and
检测项不是越多越好。每多一个 CSS.supports 调用就多一次解析开销,而老旧内核(如 IE11、Android 4.4 WebView)本身执行慢,频繁调用可能卡住主线程。
聚焦三个真实影响布局的核心点即可:
display: grid → 决定是否启用网格布局margin-inline-start → 决定是否启用逻辑属性(LTR/RTL 统一)color + var(--x) → 决定是否启用 CSS 变量(注意必须写成两参数:CSS.supports('color', 'var(--primary)'))别检测 gap 单独存在——它依赖容器是 flex 或 grid,单独检测无意义;也别检测 aspect-ratio,Chrome 88+ 才支持,但降级方案(padding-top 百分比技巧)成本高且易出错,不如直接用 JS 控制容器高度。
最常被忽略的一点:检测结果必须缓存。不要在每次组件 render 时都调用 CSS.supports,封装成一个模块级常量:
const CSS_FEATURES = { supportsGrid: typeof CSS !== 'undefined' && CSS.supports('display', 'grid'), supportsLogicalProps: typeof CSS !== 'undefined' && CSS.supports('margin-inline-start', '1rem'), supportsCSSVars: typeof CSS !== 'undefined' && CSS.supports('color', 'var(--x)'),};