purgecss icon indicating copy to clipboard operation
purgecss copied to clipboard

[Bug]: :is and :where selector lists are purged regardless of matching elements

Open chriskirknielsen opened this issue 3 years ago • 15 comments

Describe the bug

When purging CSS, if a non-blocklisted selector is present in an :is() or :where() selector (e.g. :is(h1, h2, h3), it is still purged from the resulting CSS.

To Reproduce

  1. Create a basic HTML page with an <h2>Lorem ipsum</h2> element.
  2. Create a CSS file with a declaration block of :is(h1, h2, h3) { color: red; } (placing * in front of the selector has no effect)
  3. Run PurgeCSS on the created CSS file based on the content of the created HTML file.

Expected Behavior

The resulting styles should have :is(h1, h2, h3) { color: red; } and the <h2> should show up in red. Instead the whole declaration block is missing.

Environment

purgecss: 4.1.3 Environment: macOS v12.4, Node.js v18.6.0, npm v8.13.2

Add any other context about the problem here

CSS is minified (Sass -> CSS with compressed output) before being fed to PurgeCSS. Tested with expanded styles, same result.

Running this as an HTML transform on an Eleventy build (v.2.0.0-canary14) which grabs a hardcoded comment line and replaces it with the purged CSS, see this gist. (this makes it a little more difficult to debug)

My workaround is to safelist :is and :where but this causes unused CSS to be kept since the selectors are used across the stylesheet.

Code of Conduct

  • [X] I agree to follow this project's Code of Conduct

chriskirknielsen avatar Aug 19 '22 14:08 chriskirknielsen

Same issue with the :any-link or any other selector starting with the colon

GrimLink avatar Oct 26 '22 12:10 GrimLink

@Ffloriel I see that this has been fixed on the main branch. Is there anything we can do to get it released to npm?

diegohaz avatar Apr 19 '23 06:04 diegohaz

I'll release a beta version with the fix this weekend

Ffloriel avatar Apr 19 '23 19:04 Ffloriel

It's released under the next tag for the packages purgecss and @fullhuman/postcss-purgecss npm i -D @fullhuman/postcss-purgecss@next should give you the version with the fix.

Ffloriel avatar Apr 23 '23 09:04 Ffloriel

Hi @Ffloriel. Unfortunately this issue seems to persist with version 6.0.0-alpha.0 (@fullhuman/postcss-purgecss@next). I made a test and rules like :is(h1, h2) { color: red } are still removed from the bundle.

This is quite annoying for me because I’m using a CSS framework with functional pseudo-classes everywhere. Any news about a fix?

laurentpayot avatar Jun 16 '23 10:06 laurentpayot

I just noticed that there is no difference between v6.0.0-alpha.0 (next version) and v5.0.0: https://github.com/FullHuman/purgecss/compare/v6.0.0-alpha.0...v5.0.0

Is it normal?

laurentpayot avatar Jun 16 '23 10:06 laurentpayot

I found a workaround by safelisting selectors starting with a colon this way:

safelist: {
  standard: [ /^\:[-a-z]+$/ ]
}

standard seems to be enough for my use case.

laurentpayot avatar Jun 16 '23 23:06 laurentpayot

@laurentpayot, I think, you need to check the difference between the versions the other way round like v5.0.0...v6.0.0-alpha.0.

leifmarcus avatar Sep 14 '23 17:09 leifmarcus

D’oh! :facepalm: Thanks @leifmarcus.

laurentpayot avatar Sep 14 '23 20:09 laurentpayot

Seems to have been fixed on e9a65303c8b5ca8dab29e7e860c1ba35c1a7572b. Are there any plans on publishing any of the new changes from v6.0.0-alpha.0?

bryanjhv avatar Mar 24 '24 03:03 bryanjhv

Seems to have been fixed on e9a6530. Are there any plans on publishing any of the new changes from v6.0.0-alpha.0?

It’s not the same issue.

I checked on a project using v6 and it’s not fixed despite what’s mentioned in its changelog. Even :where(body) gets fully removed, and it’s probably the most basic use case out there.

meduzen avatar Apr 05 '24 07:04 meduzen

I can confirm that this is still an issue as of version 6.0.0. Here's a minimal example that might be useful for debugging:

index.html:

<!DOCTYPE html>
<html lang="en">
  <head> <link rel="stylesheet" href="/main.css"> </head>
  <body> <h1>Some heading</h1> </body>
</html>

main.css:

/* Single pseudo-class selectors will be purged */
:is(body) {
  background: white;
}

:is(h1, h2, h3) {
  font-weight: 700;
}

/* Combining pseudo-classes with other selectors won't be purged  */
:is(body) h1 {
  color: black;
}

body :is(h1, h2, h3) {
  display: flex;
}

Running purgecss from the CLI with default options will strip the two standalone pseudo-classes but keeps the ones that are combined with other selectors.


Here's a complete log of what I have done:

$ npx purgecss --version
6.0.0

$ npx purgecss --css main.css --content index.html --output ./out  

$ cat ./out/main.css

The output from the last command is:

/* Single pseudo-class selectors will be purged */

/* Combining pseudo-classes with other selectors won't be purged  */
:is(body) h1 {
  color: black;
}

body :is(h1) {
  display: flex;
}

urob avatar Jun 12 '24 16:06 urob

I skimmed through the source code in the index.ts file in the repo and I noticed, before the level of bloat discouraged me, the hardcoding of where, is, has among other terms specific to CSS styles.

This may be a culprit as whatever logic led to their hardcoding is not ubiquitous and may fail as unique scenarios using these terms arise upon usage.

Pending the fix of this bug, here is an alternative developed by me that promises to be thorough and do better: https://www.npmjs.com/package/rmrf-css Cheers.

ogbotemi-2000 avatar Jun 26 '24 20:06 ogbotemi-2000

I can confirm that I still see this issue. For instance, the following selector gets removed:

:where(.wp-block-columns.is-layout-flex) { gap: 2em; }

As a temporary fix, I am manually unwrapping the :where selector like this:

.wp-block-columns.is-layout-flex { gap: 2em; }

cryptalith avatar Jun 27 '24 15:06 cryptalith

Hello, you may try this alternative package that I developed which has a browser-based version to do away with the quirks and bugs of PurgeCSS: https: https://www.npmjs.com/package/rmrf-css

ogbotemi-2000 avatar Jun 27 '24 22:06 ogbotemi-2000