A pseudo-class for matching elements in a selector list
npm install @csstools/postcss-is-pseudo-class[![NPM Version][npm-img]][npm-url]
[][cli-url]
[][discord]
[][css-url]
[![CSS Standard Status][css-img]][css-url]
[PostCSS Is Pseudo Class] lets you use the :is pseudo class function, following the
[CSS Selector] specification.
``css`
:is(input, button):is(:hover, :focus) {
order: 1;
}
Becomes :
`css`
input:hover {
order: 1;
}
input:focus {
order: 1;
}
button:hover {
order: 1;
}
button:focus {
order: 1;
}
Add [PostCSS Is Pseudo Class] to your project:
`bash`
npm install @csstools/postcss-is-pseudo-class --save-dev
Use [PostCSS Is Pseudo Class] as a [PostCSS] plugin:
`js
import postcss from 'postcss';
import postcssIsPseudoClass from '@csstools/postcss-is-pseudo-class';
postcss([
postcssIsPseudoClass(/ pluginOptions /)
]).process(YOUR_CSS /, processOptions /);
`
[PostCSS Is Pseudo Class] runs in all Node environments, with special instructions for:
| Node | Webpack | Gulp | Grunt |
| --- | --- | --- | --- |
The preserve option determines whether the original notation
is preserved. By default, it is not preserved.
`js`
postcss([
postcssIsPseudoClass({ preserve: true })
]).process(YOUR_CSS /, processOptions /);
`css`
:is(input, button):is(:hover, :focus) {
order: 1;
}
Becomes :
`css`
input:hover {
order: 1;
}
input:focus {
order: 1;
}
button:hover {
order: 1;
}
button:focus {
order: 1;
}
:is(input, button):is(:hover, :focus) {
order: 1;
}
The specificityMatchingName option allows you to change the selector used to adjust specificity.does-not-exist
The default value is .
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.
`js`
postcss([
postcssIsPseudoClass({ specificityMatchingName: 'something-random' })
]).process(YOUR_CSS /, processOptions /);
`css`
:is(.button, button):hover {
order: 7;
}
Becomes :
`css
.button:hover {
order: 7;
}
button:not(.something-random):hover {
order: 7;
}
`
Warn on complex selectors in :is pseudo class functions.
`js`
postcss([
postcssIsPseudoClass({ onComplexSelector: 'warning' })
]).process(YOUR_CSS /, processOptions /);
Warn when pseudo elements are used in :is pseudo class functions.
⚠️ Pseudo elements are always invalid and will be transformed to ::-csstools-invalid-.
`js`
postcss([
postcssIsPseudoClass({ onPseudoElement: 'warning' })
]).process(YOUR_CSS /, processOptions /);
`css
:is(::after):hover {
order: 1.0;
}
/ becomes /
::-csstools-invalid-after:hover {
order: 1.0;
}
`
:is takes the specificity of the most specific list item.:not
We can increase specificity with selectors, but we can't decrease it.
Converted selectors are ensured to have the same specificity as :is for the most important bit.:is
Less important bits can have higher specificity that .
Before :
specificity: 0, 2, 0%3Ais(.button%2C%20button))
`css`
:is(:hover, :focus):is(.button, button) {
order: 7;
}
After :
`css
/ specificity: [0, 2, 0] /
.button:hover {
order: 7;
}
/ specificity: [0, 2, 1] /
/ last bit is higher than it should be, but middle bit matches /
button:not(.does-not-exist):hover {
order: 7;
}
/ specificity: [0, 2, 0] /
.button:focus {
order: 7;
}
/ specificity: [0, 2, 1] /
/ last bit is higher than it should be, but middle bit matches /
button:not(.does-not-exist):focus {
order: 7;
}
`
Before :
`css`
:is(.alpha > .beta) ~ :is(:focus > .beta) {
order: 2;
}
After :
`css`
.alpha > .beta ~ :focus > .beta {
order: 2;
}
_this is a different selector than expected as .beta ~ :focus matches .beta followed by :focus._:is()
_avoid these cases._
_writing the selector without is advised here_
`css``
/ without is /
.alpha:focus > .beta ~ .beta {
order: 2;
}
If you have a specific pattern you can open an issue to discuss it.
We can detect and transform some cases but can't generalize them into a single solution that tackles all of them.
[cli-url]: https://github.com/csstools/postcss-plugins/actions/workflows/test.yml?query=workflow/test
[css-img]: https://cssdb.org/images/badges/is-pseudo-class.svg
[css-url]: https://cssdb.org/#is-pseudo-class
[discord]: https://discord.gg/bUadyRwkJS
[npm-img]: https://img.shields.io/npm/v/@csstools/postcss-is-pseudo-class.svg
[npm-url]: https://www.npmjs.com/package/@csstools/postcss-is-pseudo-class
[CSS Selector]: https://www.w3.org/TR/selectors-4/#matches
[PostCSS]: https://github.com/postcss/postcss
[PostCSS Is Pseudo Class]: https://github.com/csstools/postcss-plugins/tree/main/plugins/postcss-is-pseudo-class