CSS 호환성
CSS 호환성 (CSS Compatible)
Ant Design은 최신 브라우저의 최근 2개 버전을 지원해요. 레거시 브라우저와 호환되어야 한다면 실제 요구에 따라 다운그레이드 처리를 해 주면 돼요.
출처: 문서
본문
기본 스타일 호환성
Ant Design은 최신 브라우저의 최근 2개 버전을 지원해요. 레거시 브라우저와 호환되어야 한다면 실제 요구에 따라 다운그레이드 처리를 해 주세요:
| Feature | antd version | Compatibility | Minimum Chrome Version | Compatibility workaround |
|---|---|---|---|---|
| :where Selector | >=5.0.0 |
caniuse | Chrome 88 | <StyleProvider hashPriority="high"> |
| CSS Logical Properties | >=5.0.0 |
caniuse | Chrome 89 | <StyleProvider transformers={[legacyLogicalPropertiesTransformer]}> |
더 오래된 브라우저를 지원해야 한다면 @ant-design/cssinjs의 StyleProvider를 사용해 실제 요구에 맞게 다운그레이드 처리를 하세요.
선택자 안의 :where
Ant Design의 CSS-in-JS 기능은 기본적으로 ":where" 선택자를 사용해 CSS 선택자 특이도(specificity)를 낮추므로, 사용자가 업그레이드할 때 커스텀 스타일을 조정하는 추가 비용을 줄여 줘요. 하지만 ":where" 문법의 호환성은 오래된 브라우저에서 비교적 좋지 않아요 (호환성). 특정 시나리오에서 오래된 브라우저를 지원해야 한다면 @ant-design/cssinjs로 기본 특이도 낮추기를 끌 수 있어요 (antd와 버전 일치를 확인해 주세요).
import { StyleProvider } from '@ant-design/cssinjs';
// Config `hashPriority` to `high` instead of default `low`
// Which will remove `:where` wrapper
export default () => (
<StyleProvider hashPriority="high">
<MyApp />
</StyleProvider>
);
이러면 :where를 클래스 선택자로 바꿔 줘요:
-- :where(.css-bAMboO).ant-btn {
++ .css-bAMboO.ant-btn {
color: #fff;
}
참고: :where 다운그레이드를 끄면 일부 스타일의 우선순위를 수동으로 조정해야 할 수 있어요. 또는 PostCSS 플러그인을 사용해서 애플리케이션 CSS 선택자 우선순위를 높일 수도 있어요. PostCSS에는 이를 도와주는 플러그인이 많아요. 예를 들어:
플러그인으로 우선순위 올리기:
-- .my-btn {
++ #root .my-btn {
background: red;
}
CSS Logical Properties
- antd 버전:
>=5.0.0 - MDN:CSS Logical Properties
- 브라우저 호환성: caniuse
- 지원되는 최소 Chrome 버전: 89
- 기본 활성화: 예
LTR과 RTL 스타일을 통일하기 위해 Ant Design은 CSS 논리 속성(logical properties)을 사용해요. 예를 들어 원래의 margin-left가 margin-inline-start로 바뀌어서, LTR과 RTL 양쪽에서 모두 시작 위치 간격이 되도록 해요. 오래된 브라우저와 호환되어야 한다면 @ant-design/cssinjs의 StyleProvider로 transformers를 구성할 수 있어요:
import { legacyLogicalPropertiesTransformer, StyleProvider } from '@ant-design/cssinjs';
// `transformers` provides a way to transform CSS properties
export default () => (
<StyleProvider transformers={[legacyLogicalPropertiesTransformer]}>
<MyApp />
</StyleProvider>
);
켜면 스타일이 CSS 논리 속성을 다음과 같이 다운그레이드해요:
.ant-modal-root {
-- inset: 0;
++ top: 0;
++ right: 0;
++ bottom: 0;
++ left: 0;
}
@layer
- antd 버전:
>=5.17.0 - MDN:CSS @layer
- 브라우저 호환성: caniuse
- 지원되는 최소 Chrome 버전: 99
- 기본 활성화: 아니오
Ant Design은 5.17.0부터 통일된 CSS 우선순위 다운그레이드를 위해 @layer 구성을 지원해요. 다운그레이드 후 antd의 스타일은 항상 기본 CSS 선택자 우선순위보다 낮아져서, 사용자가 스타일을 쉽게 덮어쓸 수 있어요 (@layer의 브라우저 호환성을 꼭 확인해 주세요). layer를 활성화하면 자식 요소 반드시 ConfigProvider로 감싸 아이콘 관련 스타일을 갱신해야 해요:
import { StyleProvider } from '@ant-design/cssinjs';
import { ConfigProvider } from 'antd';
export default () => (
<StyleProvider layer>
<ConfigProvider>
<MyApp />
</ConfigProvider>
</StyleProvider>
);
antd 스타일은 @layer 안에 캡슐화되어 우선순위가 낮아져요:
++ @layer antd {
:where(.css-bAMboO).ant-btn {
color: #fff;
}
++ }
⚠️ zeroRuntime 시나리오 참고 (6.0.0에서 추가됨)
zeroRuntime이 활성화되면 Ant Design 스타일은 독립된 antd.css 파일로 미리 컴파일돼요. @layer 특이도 낮추기 메커니즘도 함께 켠다면, antd.css가 반드시 같은 레이어(예: layer(antd)) 안에 들어가도록 해야 해요. 그렇지 않으면 그 특이도가 StyleProvider가 주입한 스타일보다 높아져서, 낮추기 메커니즘이 실패하거나 의도치 않은 오버라이드 동작이 발생할 수 있어요.
/* global.css / app.css */
@layer theme, base, antd, components, utilities;
/* The precompiled antd.css output by zeroRuntime must explicitly specify a layer */
@import url(antd.css) layer(antd);
@import ... layer() 문법을 사용할 수 없다면, 빌드 과정에서 내용을 감싸 주는 방법을 쓸 수 있어요:
@layer antd {
/* contents of antd.css */
}
autoPrefixer
- antd 버전:
>=6.0.0 - 브라우저 호환성: 더 넓은 브라우저 지원을 위해 자동으로 브라우저 접두사 추가
- 기본 활성화: 아니오
일부 스타일은 브라우저 접두사에 의존해 호환돼요. autoPrefixer 트랜스포머는 스타일에 브라우저 접두사를 자동으로 추가해, 서로 다른 브라우저에서도 잘 동작하게 보장해 줘요.
import { autoPrefixTransformer, StyleProvider } from '@ant-design/cssinjs';
export default () => (
<StyleProvider transformers={[autoPrefixTransformer]}>
<MyApp />
</StyleProvider>
);
최종 변환된 스타일:
.sample-box {
-- user-select: none;
++ -webkit-user-select: none;
++ -moz-user-select: none;
++ -ms-user-select: none;
++ user-select: none;
}
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;
}
}
옵션
| Parameter | Description | Type | Default |
|---|---|---|---|
| rootValue | Font size of the root element | number |
16 |
| precision | Decimal places for the converted value | number |
5 |
| mediaQuery | Whether to convert px in media queries | boolean |
false |
더 자세한 내용은 px2rem.ts#Options를 참고하세요.
Shadow DOM 사용
Shadow DOM 시나리오에서는 <style /> 태그 삽입이 일반 DOM과 달라서, @ant-design/cssinjs의 StyleProvider로 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 CSS, Emotion, styled-components 같은 다른 스타일 라이브러리와 공존해야 할 수도 있어요. 전통적인 CSS 솔루션과 달리, 이런 서드파티 라이브러리는 CSS 선택자 우선순위를 높여서 antd 스타일을 덮어쓰기가 어려운 경우가 많아요. antd에 @layer를 구성해 CSS 선택자 가중치를 낮추고, @layer 순서를 정리해서 스타일 오버라이드 문제를 해결할 수 있어요:
antd @layer 구성
앞서 언급했듯이 StyleProvider를 사용할 때는 ConfigProvider로 감싸 아이콘 관련 스타일을 갱신해야 해요:
import { StyleProvider } from '@ant-design/cssinjs';
export default () => (
<StyleProvider layer>
<ConfigProvider>
<MyApp />
</ConfigProvider>
</StyleProvider>
);
TailwindCSS @layer 정리
아래 구성을 시작하기 전에 @layer 기능을 먼저 활성화해야 해요.
TailwindCSS v3
global.css에서 @layer를 조정해 스타일 오버라이드 순서를 제어하세요. tailwind-base를 antd 앞에 두세요:
@layer tailwind-base, antd;
@layer tailwind-base {
@tailwind base;
}
@tailwind components;
@tailwind utilities;
TailwindCSS v4
global.css에서 @layer를 조정해 스타일 오버라이드 순서를 제어하세요. antd를 올바른 위치에 두세요:
@layer theme, base, antd, components, utilities;
@import 'tailwindcss';
reset.css와 antd.css
Ant Design의 reset.css를 사용한다면, 특이도가 낮아진 antd 스타일을 덮어쓰지 않도록 그것을 특정 @layer에 배정해야 해요. 마찬가지로 zeroRuntime 시나리오에서 antd.css를 별도로 임포트한다면, 반드시 layer(antd) 안에 두어 레이어 계층을 일관되게 유지해야 해요:
/* Both reset.css and antd.css must specify a layer */
@layer reset, antd;
/* reset styles */
@import url(reset.css) layer(reset);
/* antd styles */
@import url(antd.css) layer(antd);
이렇게 하면 다음이 보장돼요:
- reset.css가
@layer로 낮춰진 Ant Design 스타일을 덮어쓰지 않아요 - (zeroRuntime 모드에서) antd.css가 StyleProvider가 주입한 레이어와 정렬을 유지해요
- Tailwind, Emotion 또는 다른 CSS-in-JS 라이브러리 같은 서드파티 스타일링 시스템과도 레이어 순서가 올바르게 동작해요
다른 CSS-in-JS 라이브러리와 함께
antd에 @layer를 구성한 뒤에는 다른 CSS-in-JS 라이브러리에는 추가 설정이 필요 없어요. 여러분의 CSS-in-JS가 antd 스타일을 완전히 덮어쓸 수 있어요.
SSR 시나리오
SSR을 사용할 때 스타일은 종종 <style />로 HTML에 인라인 렌더링돼요. 이때 특정 @layer 우선순위 순서가 있는 스타일이 @layer를 사용하기 전에 로드되도록 확인해 주세요.
❌ 잘못된 예
<head>
<!-- SSR Injection style -->
<style>
@layer antd {
/** ... */
}
</style>
<!-- css file contains @layer xxx, antd; -->
<link rel="stylesheet" href="/b9a0m0b9o0o3.css" />
<!-- or write @layer xxx, antd; in html directly -->
<style>
@layer xxx, antd;
</style>
</head>
✅ 올바른 예
<head>
<!-- css file contains @layer xxx, antd; -->
<link rel="stylesheet" href="/b9a0m0b9o0o3.css" />
<!-- or write @layer xxx, antd; in html directly -->
<style>
@layer xxx, antd;
</style>
<!-- SSR Injection style -->
<style>
@layer antd {
/** ... */
}
</style>
</head>