[Bug]: Most pseudo-classes incorrectly purged when there is no selector before it
Describe the bug
It removes psedo-classes without a selector before it.
/* This will be removed and purged incorrectly */
:hover { }
:not(:hover) { }
:where() {}
:where(:hover) {}
etc..
/* This will not be removed and purged incorrectly */
*:hover { }
.class:hover { }
#id:hover { }
[attribute]:hover { }
::after { }
::before { }
and etc.
It doesn't affect pseudo-elements like ::after but affects pseudo-classes. There are some exceptions which are :root but I haven't found more exceptions beyond that
The bug can be sourced from https://purgecss.com/extractors.html
Does not consider special characters such as
@, :, /
To Reproduce
Already described
Expected Behavior
I was expecting them to be not removed in the CSS
Environment
OS: Linux Mint; Package: purgecss; Version: 6.0.0;
Add any other context about the problem here
No response
Code of Conduct
- [x] I agree to follow this project's Code of Conduct
Just noticed that in the Astro integration. It is particularly problematic with things like:
:where(h1, h2, h3) {
...
}
I use a CSS library called Open Props and it uses :where(html) to contain the variables to avoid any specificty conflict and I noticed that it affected other pseudo-selectors aswell
Just noticed that in the Astro integration. It is particularly problematic with things like:
:where(h1, h2, h3) { ... }
You can circumvent this by adding the * or global selector before it and it will be purged correctly. The only issue with this is that it may decrease performance
As of 👆, it seems some of the pseudo-class issues are fixed but not entirely. Notably, the combination of :is and :not don't seem to work as expected. That is given this:
is(button, input):not(.some-class) { ... }
The rule will get purged even if you have a button or input without .some-class in your HTML.
Repro at https://github.com/fongandrew/purgecss-is-not-bug-repro.
+1 This breaks optimization of the default Gutenberg styles in WordPress because they use these selectors a lot. E.g.,
.is-layout-constrained > :where(:not(.alignleft):not(.alignright):not(.alignfull)){
max-width: var(--wp--style--global--content-size);
margin-left: auto !important;
margin-right: auto !important;
}
gets removed on my pages with the .alignwide layout despite the fact that they match the selector.
Similarly, I also lose this selector despite the fact that .wp-site-blocks has children.
:where(.wp-site-blocks) > :first-child {
margin-block-start: 0;
}