ant-design
ant-design copied to clipboard
CSS cascade layers support
What problem does this feature solve?
Trying to override antd styles requires the selectors to be more specific than antd's selectors. When using CSS utilities such as tailwind, the only way to increase specificity is to make all properties !important
, which then becomes even harder to override. By giving the option to wrap antd's styles in a cascade layer, it will be much easier to cleanly override its styles when needed.
What does the proposed API look like?
<ConfigProvider cascadeLayer="framework" />
In the earlier version, @ant-design/cssinjs
use @layer
to reduce css priority. But we found that it's too easy to conflict with other lib's css:
// Layer
@layer {
.sample {
a {
color: red;
&:hover {
color: blue;
}
}
}
}
// Third part lib
a {
color: green; // Which will override `:hover` also
}
So we revert and use :where
to keep the css selector priority same as v4.
Interesting. It is tricky to come up with a solution that helps in every situation. There are many different approaches for customizing the styles. If we can get a few of those working, I think most use cases will be covered.
Option 1 - Provide tokens for (almost) everything This would reduce the need to override the CSS with a 3rd party library. But there would still be edge cases.
Option 2 - Provide built-in CSS utilities for overriding
Mantine provides the sx
prop for example. I think Chakra provides tailwind classes. If antd had a CSS utilities solution, the specificity could be set internally such that it avoids conflicts. And most users would no longer need a 3rd party CSS solution.
Option 3 - Provide a mechanism to control the specificity of selectors Basically CSS cascade layers. But then we run into the issue above. This should be a last resort I think. In v4, I was able to use postcss-assign-layer plugin to move all antd styles into a layer. But the plugin only works in imported css, not css that is injected into the DOM like in v5.
In the earlier version,
@ant-design/cssinjs
use@layer
to reduce css priority. But we found that it's too easy to conflict with other lib's css:// Layer @layer { .sample { a { color: red; &:hover { color: blue; } } } } // Third part lib a { color: green; // Which will override `:hover` also }
So we revert and use
:where
to keep the css selector priority same as v4.
We've also paused migrating to v5 because the css styling is too much of a pain. The :where selector doesn't leave the CSS priority the same as v4. v5's is higher, which I believe the original poster was highlighting. An example can be found on ant-design's own website:
v4 - Lovely and easy to override https://4x.ant.design/components/button/
.ant-btn-primary {
v5 - Difficult and cumbersome https://ant.design/components/button
:where(.css-j0nf2s).ant-btn-primary {
The original philosophy of v4 of antd as a base library being easily overridden was the correct one.
For anyone looking, the v4 to v5 migration guide has the wrong link, so the hash priority can be lowered via this page: https://ant.design/docs/react/compatible-style
heads up for this feature, it will be so much cleaner user-space-override code with @layer directive.
But we found that it's too easy to conflict with other lib's css
It may be an issue for legacy projects or mixed UI kit projects, but I can't be really sure it's a problem that should be solved by antd. You can make @layer
usage optional, now there is no way to move all antd styles to separate layer at all. Please provide this choice to consumer. For example, in my project we don't have any other libs and still fighting with :where()
every day. If all antd styled can be moved to layer it will be so easy to override.