Skip to content

Commit 557d51d

Browse files
authored
docs: Blog about v6 css (ant-design#53899)
* docs: init * docs: env ver
1 parent 7707c25 commit 557d51d

File tree

4 files changed

+508
-0
lines changed

4 files changed

+508
-0
lines changed

docs/blog/css-tricks.en-US.md

Lines changed: 223 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,223 @@
1+
---
2+
title: CSS in v6
3+
date: 2025-05-23
4+
author: zombieJ
5+
---
6+
7+
During the development of Ant Design v6, since there is no longer any need to consider IE compatibility, we modified some components to use CSS variables. This resulted in a smaller CSS footprint and better performance. Today, let's talk about some aspects of CSS variables.
8+
9+
## Variants
10+
11+
In v5, some components supported the `variant` property to implement different styles, with the Button component being a typical example:
12+
13+
![Variant Button](https://mdn.alipayobjects.com/huamei_iwk9zp/afts/img/A*ApyYQpXQQfgAAAAAAAAAAAAADgCCAQ/original)
14+
15+
(Combined with `color` to achieve different button combinations)
16+
17+
In v5, the combination of Button variants and color would create a repetitive set of combinational styles:
18+
19+
```css
20+
/* Sample code. Not used in real world. */
21+
.ant-btn-solid.ant-btn-red {
22+
color: #fff;
23+
background: 1px solid red;
24+
}
25+
26+
.ant-btn-solid.ant-btn-blue {
27+
color: #fff;
28+
background: 1px solid blue;
29+
}
30+
31+
.ant-btn-outlined.ant-btn-red {
32+
color: #fff;
33+
border: 1px solid red;
34+
}
35+
36+
.ant-btn-outlined.ant-btn-blue {
37+
color: #fff;
38+
border: 1px solid blue;
39+
}
40+
41+
/* ... */
42+
```
43+
44+
After converting to CSS variables, the logic shifts from directly defining styles to managing the color palette. Thus, after defining a basic set of colors, you can effortlessly generate styles via variables:
45+
46+
```css
47+
/* Sample code. Not used in real world. */
48+
/* Template Part */
49+
.ant-btn {
50+
color: var(--ant-btn-color);
51+
background: var(--ant-btn-background);
52+
border-color: var(--ant-btn-border-color);
53+
border-width: 1px;
54+
border-style: solid;
55+
}
56+
57+
.ant-btn-solid {
58+
--ant-btn-color: #fff;
59+
--ant-btn-background: var(--ant-color-solid);
60+
}
61+
62+
.ant-btn-outlined {
63+
--ant-btn-color: var(--ant-color-solid);
64+
--ant-btn-border-color: var(--ant-color-solid);
65+
}
66+
67+
/* CSS Variables. The more color you have, the more size to save. */
68+
.ant-btn-red {
69+
--ant-color-solid: red;
70+
}
71+
72+
.ant-btn-blue {
73+
--ant-color-solid: blue;
74+
}
75+
76+
/* ... */
77+
```
78+
79+
## Style Overrides
80+
81+
With CSS variables, overriding styles on the user side becomes much simpler. In the past, developers had to override styles for each state and consider specificity:
82+
83+
```css
84+
.ant-btn-solid.my-btn:not(:disabled) {
85+
background: #f00;
86+
}
87+
88+
.ant-btn-solid.my-btn:not(:disabled):hover {
89+
background: #e00;
90+
}
91+
92+
.ant-btn-solid.my-btn:not(:disabled):active {
93+
background: #d00;
94+
}
95+
96+
.ant-btn-outlined.my-btn:not(:disabled) {
97+
color: #f00;
98+
border-color: #f00;
99+
}
100+
101+
.ant-btn-outlined.my-btn:not(:disabled):hover {
102+
color: #e00;
103+
border-color: #e00;
104+
}
105+
106+
.ant-btn-outlined.my-btn:not(:disabled):active {
107+
color: #d00;
108+
border-color: #d00;
109+
}
110+
```
111+
112+
Overriding CSS variables, however, is much simpler:
113+
114+
```css
115+
.ant-btn-outlined.my-btn {
116+
--ant-color-solid: #f00;
117+
--ant-color-solid-hover: #e00;
118+
--ant-color-solid-active: #d00;
119+
}
120+
```
121+
122+
## Conditional Compatibility
123+
124+
In v6, to achieve a more semantic structure, we adjusted the DOM of many components and also cleaned up the compatible Component Tokens provided during the v4 to v5 Less migration (more values are computed rather than manually configured by developers). However, to avoid affecting existing users, we aimed for maximum compatibility.
125+
126+
One example is that when a certain token exists, we use an alternative style:
127+
128+
```less
129+
.sample {
130+
color: blue;
131+
}
132+
133+
/* How to if? */
134+
if (customVar exist) {
135+
.sample {
136+
color: red;
137+
}
138+
}
139+
```
140+
141+
One idea was to add an extra `className` to the component based on the existence of the token:
142+
143+
```jsx
144+
const Sample = () => {
145+
const { token } = useToken();
146+
147+
// Sad. Component token is not exist in token.
148+
if (token.components.sample.customVar) {
149+
// ...
150+
}
151+
};
152+
```
153+
154+
Unfortunately, the component token is not available in `useToken`. It is only generated asynchronously during the component's rendering effect to avoid unnecessary performance overhead. Therefore, using conditional logic in CSS is a better option; here, we use `@container` to implement conditional logic:
155+
156+
```css
157+
/* Current container support css var `--custom-var` */
158+
@container style(--custom-var) {
159+
/* ... */
160+
}
161+
```
162+
163+
<code src="./css-tricks/condition.tsx">Conditional Styles</code>
164+
165+
It is important to note that the CSS variable query in `@container` is not yet supported by Firefox. Therefore, in v6, we do not rely on `@container` as the primary functionality, but rather as a fallback compatibility mechanism.
166+
167+
## @scope
168+
169+
If there is one of the most enticing properties in CSS, it would be `@scope`. In v5, we used `:where` to implement CSS namespaces, isolating styles for different versions or themes of antd components:
170+
171+
```css
172+
/* Theme 1 */
173+
:where(.css-BamBoo) {
174+
.ant-btn {
175+
color: red;
176+
}
177+
}
178+
179+
/* Theme 2 */
180+
:where(.css-LIghT) {
181+
.ant-btn {
182+
color: blue;
183+
}
184+
}
185+
```
186+
187+
However, this approach can sometimes cause issues with nested logic. For example, in the following case, styles for `span` under `Theme1` affect `Theme2`:
188+
189+
```css
190+
/* Theme 1 */
191+
:where(.css-BamBoo) {
192+
.component-a span {
193+
color: red;
194+
}
195+
}
196+
197+
/* Theme 2 */
198+
:where(.css-LIghT) {
199+
.component-b {
200+
color: blue;
201+
}
202+
}
203+
```
204+
205+
```tsx
206+
<div className="component-a css-BamBoo">
207+
<div className="component-b css-LIghT">
208+
<span>Hello World</span>
209+
</div>
210+
</div>
211+
```
212+
213+
Whereas `@scope` can perfectly solve this problem:
214+
215+
```css
216+
@scope (.component-a) to (span) {
217+
/* ... */
218+
}
219+
```
220+
221+
<code src="./css-tricks/scope.tsx">Scope Impact</code>
222+
223+
However, similarly, `@scope` is not yet supported by Firefox. Applying it in v6 would result in Firefox users being unable to use antd components. Hence, you may only see it in the next major version.

0 commit comments

Comments
 (0)