ant-design/docs/react/compatible-style.zh-CN.md

8.8 KiB
Raw Blame History

group order title
title
进阶使用
1 样式兼容

默认样式兼容性说明

Ant Design 5.x 支持最近 2 个版本的现代浏览器。默认情况下,我们使用了一些现代 CSS 特性来提高样式的可维护性和可扩展性,这些特性在旧版浏览器中可能不被支持,好在我们可以通过一些降级兼容方案来解决。

特性 antd 版本 兼容性 最低 Chrome 版本 降级兼容方案
:where 选择器 >=5.0.0 caniuse Chrome 88 <StyleProvider hashPriority="high">
CSS 逻辑属性 >=5.0.0 caniuse Chrome 89 <StyleProvider transformers={[legacyLogicalPropertiesTransformer]}>

如果你需要兼容旧版浏览器,请根据实际需求使用 StyleProvider 降级处理。

:where 选择器

  • 支持版本:>=5.0.0
  • MDN 文档::where
  • 浏览器兼容性:caniuse
  • Chrome 最低支持版本88
  • 默认启用:是

Ant Design 的 CSS-in-JS 默认通过 :where 选择器降低 CSS Selector 优先级,以减少用户升级时额外调整自定义样式的成本,不过 :where 语法的兼容性在低版本浏览器比较差。在某些场景下你如果需要支持旧版浏览器,你可以使用 @ant-design/cssinjs 取消默认的降权操作(请注意版本保持与 antd 一致):

import { StyleProvider } from '@ant-design/cssinjs';

// `hashPriority` 默认为 `low`,配置为 `high` 后,
// 会移除 `:where` 选择器封装
export default () => (
  <StyleProvider hashPriority="high">
    <MyApp />
  </StyleProvider>
);

切换后,样式将从 :where 切换为类选择器:

--  :where(.css-bAMboO).ant-btn {
++  .css-bAMboO.ant-btn {
      color: #fff;
    }

注意:关闭 :where 降权后,你可能需要手动调整一些样式的优先级。亦或者使用 PostCSS 插件提升应用样式的优先级PostCSS 提供了非常多的插件来调整优先级,你可以自行按需选择,例如:

通过插件配置,将你的 css 样式进行提升:

--  .my-btn {
++  #root .my-btn {
      background: red;
    }

CSS 逻辑属性

  • 支持版本:>=5.0.0
  • MDN 文档::where
  • 浏览器兼容性:caniuse
  • Chrome 最低支持版本89
  • 默认启用:是

为了统一 LTR 和 RTL 样式Ant Design 使用了 CSS 逻辑属性。例如原 margin-left 使用 margin-inline-start 代替,使其在 LTR 和 RTL 下都为起始位置间距。如果你需要兼容旧版浏览器(如 360 浏览器、QQ 浏览器 等等),可以通过 @ant-design/cssinjsStyleProvider 配置 transformers 将其转换:

import { legacyLogicalPropertiesTransformer, StyleProvider } from '@ant-design/cssinjs';

// `transformers` 提供预处理功能将样式进行转换
export default () => (
  <StyleProvider transformers={[legacyLogicalPropertiesTransformer]}>
    <MyApp />
  </StyleProvider>
);

切换后,样式将降级 CSS 逻辑属性:

.ant-modal-root {
-- inset: 0;
++ top: 0;
++ right: 0;
++ bottom: 0;
++ left: 0;
}

@layer 样式优先级降权

  • 支持版本:>=5.17.0
  • MDN 文档:@layer
  • 浏览器兼容性:caniuse
  • Chrome 最低支持版本99
  • 默认启用:否

Ant Design 从 5.17.0 起支持配置 layer 进行统一降权。经过降权后antd 的样式将始终低于默认的 CSS 选择器优先级,以便于用户进行样式覆盖(请务必注意检查 @layer 浏览器兼容性):

import { StyleProvider } from '@ant-design/cssinjs';

export default () => (
  <StyleProvider layer>
    <MyApp />
  </StyleProvider>
);

antd 的样式会被封装在 @layer 中,以降低优先级:

++  @layer antd {
      :where(.css-bAMboO).ant-btn {
        color: #fff;
      }
++  }

rem 适配

在响应式网页开发中,需要一种方便且灵活的方式来实现页面的适配和响应式设计。px2remTransformer 转换器可以快速而准确地将样式表中的像素单位转换为相对于根元素HTML 标签)的 rem 单位,实现页面的自适应和响应式布局。

import { px2remTransformer, StyleProvider } from '@ant-design/cssinjs';

const px2rem = px2remTransformer({
  rootValue: 32, // 32px = 1rem; @default 16
});

export default () => (
  <StyleProvider transformers={[px2rem]}>
    <MyApp />
  </StyleProvider>
);

最终转换后的样式:

 .px2rem-box {
-  width: 400px;
+  width: 12.5rem;
   background-color: green;
-  font-size: 32px;
+  font-size: 1rem;
   border: 10PX solid #f0f;
 }

 @media only screen and (max-width: 600px) {
   .px2rem-box {
     background-color: red;
-    margin: 10px;
+    margin: 0.3125rem;
   }
 }

配置项

参数 说明 类型 默认值
rootValue 根元素字体大小 number 16
precision 转换后的小数点位数 number 5
mediaQuery 是否转换媒体查询中的 px boolean false

详细请参考: px2rem.ts#Options

Shadow DOM 场景

在 Shadow DOM 场景中,由于其添加 <style /> 标签的方式与普通 DOM 不同,所以需要使用 @ant-design/cssinjsStyleProvider 配置 container 属性用于设置插入位置:

import { StyleProvider } from '@ant-design/cssinjs';
import { createRoot } from 'react-dom/client';

const shadowRoot = someEle.attachShadow({ mode: 'open' });
const container = document.createElement('div');
shadowRoot.appendChild(container);
const root = createRoot(container);

root.render(
  <StyleProvider container={shadowRoot}>
    <MyApp />
  </StyleProvider>,
);

兼容三方样式库

在某些情况下,你可能需要 antd 与其他样式库共存,比如 Tailwind CSSEmotionstyled-components 等。不同于传统 CSS 方案,这些三方库往往不太容易通过提升 CSS 选择器优先级的方式覆盖 antd 的样式。你可以通过为 antd 配置 @layer 降低其 CSS 选择器权重,同时通过合理安排 @layer 顺序来解决样式覆盖问题:

antd 配置 @layer

import { StyleProvider } from '@ant-design/cssinjs';

export default () => (
  <StyleProvider layer>
    <MyApp />
  </StyleProvider>
);

TailwindCSS 排布 @layer

在 global.css 中,调整 @layer 来控制样式的覆盖顺序。让 tailwind-base 置于 antd 之前:

@layer tailwind-base, antd;

@layer tailwind-base {
  @tailwind base;
}
@tailwind components;
@tailwind utilities;

reset.css

如果你使用了 antd 的 reset.css 样式,你需要为其也指定 @layer 以防止将 antd 降权的样式覆盖:

@layer reset, antd;

@import url(reset.css) layer(reset);

其他 CSS-in-JS 库

当你为 antd 配置完 @layer 后,你不需要为其他的 CSS-in-JS 库做任何额外的配置。你的 CSS-in-JS 已经可以完全覆盖 antd 的样式了。

SSR 场景

在 SSR 场景下,样式往往会通过 <style /> 内联渲染到 HTML 中。此时请务必确保你的样式顺序中指定 @layer 优先级顺序的样式在 @layer 被使用之前被加载。

错误的写法

<head>
  <!-- SSR 注入样式 -->
  <style>
    @layer antd {
      /** ... */
    }
  </style>

  <!-- css 文件中包含 @layer xxx, antd; -->
  <link rel="stylesheet" href="/b9a0m0b9o0o3.css" />
  <!-- or 直接书写 @layer xxx, antd; 在 html 中 -->
  <style>
    @layer xxx, antd;
  </style>
</head>

正确的写法

<head>
  <!-- css 文件中包含 @layer xxx, antd; -->
  <link rel="stylesheet" href="/b9a0m0b9o0o3.css" />
  <!-- or 直接书写 @layer xxx, antd; 在 html 中 -->
  <style>
    @layer xxx, antd;
  </style>

  <!-- SSR 注入样式 -->
  <style>
    @layer antd {
      /** ... */
    }
  </style>
</head>