Warning
Experimental version of CSS Has Pseudo
EXPERIMENTAL CSS Has Pseudo lets you style elements relative to other elements in CSS, following the Selectors Level 4 specification.
body:has(:focus) {
background-color: yellow;
}
/* becomes */
[csstools-has-2q-33-2s-3d-1m-2w-2p-37-14-1m-2u-33-2r-39-37-15]:not(does-not-exist) {
background-color: yellow;
}
body:has(:focus) {
background-color: yellow;
}
EXPERIMENTAL CSS Has Pseudo duplicates rules using the :has
pseudo-class with a [has]
attribute selector. The preservation of the original :has
rule can be
disabled using the preserve
option.
Add EXPERIMENTAL CSS Has Pseudo to your project:
npm install @csstools/css-has-pseudo-experimental --save-dev
Use EXPERIMENTAL CSS Has Pseudo as a PostCSS plugin:
const postcss = require('postcss');
const cssHasPseudoExperimental = require('@csstools/css-has-pseudo-experimental');
postcss([
cssHasPseudoExperimental(/* pluginOptions */)
]).process(YOUR_CSS /*, processOptions */);
EXPERIMENTAL CSS Has Pseudo runs in all Node environments, with special instructions for:
Node | PostCSS CLI | Webpack | Gulp | Grunt |
---|
The preserve
option defines whether the original selector should remain. By
default, the original selector is preserved.
cssHasPseudoExperimental({ preserve: false });
body:has(:focus) {
background-color: yellow;
}
/* becomes */
[csstools-has-2q-33-2s-3d-1m-2w-2p-37-14-1m-2u-33-2r-39-37-15]:not(does-not-exist) {
background-color: yellow;
}
The specificityMatchingName
option allows you to change to selector that is used to adjust specificity.
The default value is does-not-exist
.
If this is an actual class, id or tag name in your code, you will need to set a different option here.
See how :not
is used to modify specificity.
postcss([
cssHasPseudoExperimental({ specificityMatchingName: 'something-random' })
]).process(YOUR_CSS /*, processOptions */);
Before :
.x:has(> #a:hover) {
order: 11;
}
After :
[csstools-has-1a-3c-1m-2w-2p-37-14-1q-w-z-2p-1m-2w-33-3a-2t-36-15]:not(#does-not-exist):not(.does-not-exist) {
order: 11;
}
:has
transforms will result in at least one tag selector with specificity 0, 1, 0
.
If your selector has only tags we won't be able to match the original specificity.
Before :
figure:has(> img)
After :
[csstools-has-2u-2x-2v-39-36-2t-1m-2w-2p-37-14-1q-w-2x-31-2v-15]:not(does-not-exist):not(does-not-exist)
As selectors are encoded this plugin (or postcss-preset-env
) must be run after any other plugin that transforms selectors.
For postcss-preset-env
we take care to handle this for you.
If other plugins are used you need to place these in your config before postcss-preset-env
or css-has-pseudo
.
Please let us know if you have issues with plugins that transform selectors. Then we can investigate and maybe fix these.
When you use postcss-preset-env
you must disable the regular plugin.
The experimental plugin must be added after any other plugin that modifies selectors.
plugins: [
// other plugins
postcssPresetEnv({
features: {
'css-has-pseudo': false
}
}),
// other plugins
cssHasPseudoExperimental(), // last
]