Purgecss: Css attribute selectors [Request]

Created on 27 Nov 2017  路  19Comments  路  Source: FullHuman/purgecss

I can't seem to find a way to get purgecss to work with css selectors like [class*="section-"] or [title~="flower"].

Is there a method I'm overlooking or if not, is there a way to implement this?

bug

All 19 comments

This is a webpack setup, but the configuration options are the same.

new PurgecssPlugin({
  whitelistPatterns: [new RegExp('frame')]
})

This will match all selectors and classes that has frame. For v0.13.1.
See here

There is no method to implement this but as @pxwee5 pointed out, you can specified regex to tell purgecss not to remove some selectors. See here

The whitelistPatterns only checks for [class*=classes] (and different types of selectors).

@Ffloriel, is there a way to match for the entire thing? E.g. [class*=classes] or is it not necessary at all? What if I want to whitelist all css class selectors?

More Info

Also, if I have these 2 classes:

.flexgrid {}
.flexgrid > [class*=w-] {}

and I am calling .flexgrid on the parent div to initiate flexgrid on my div like so:

<div class="flexgrid">
  <div class="w-6/12 md:w-3/12">Content<div>
  <div class="w-6/12 md:w-3/12">Content<div>
<div>

Only .flexgrid {} gets included into the css file, .flexgrid > [class*=w-] {} gets purged. By right .flexgrid is part of .flexgrid > [class*=w-] {} selector and should get included into the css file. Isn't that how it's supposed to work?

I have tried the following configurations and all failed:

whitelist: ['html', 'body', 'flexgrid', '.flexgrid'],
whitelistPatterns: [new RegExp('flexgrid')], 

Some help would be appreciated :)

EDIT

The following works, but man it took me abit of time to figure it out.

whitelistPatterns: [new RegExp('^w-$')]

I see, I think what you need is to define a custom extractor. Check this gist for using purgecss with tailwindcss
Let me know if it solves the problem.

According to my tests and from what I found out, a custom extractor is for custom extraction of the glob files, not the CSS files. Let me know if I'm wrong.

By default, selectors like md:w-3/12 are not extracted from the files (because of the characters : and /). So purgecss will not see those as used and will remove them from the css files.

Correct me if I'm wrong. Are you saying that the custom extractor will extract strings from both the css and the html files?

No. Extractors are used to extract selectors from content files (html, pug, ...)
If you have the following css:

w-6\/12 {
    color: green;
}
md\:w-3\/12 {
    color: blue;
}

and an html file:

<div class="flexgrid">
  <div class="w-6/12 md:w-3/12">Content<div>
  <div class="w-6/12 md:w-3/12">Content<div>
<div>

First, purgecss will use an extractor to determine which selectors are used. The default extractor will considered div, flexgrid but not w-6/12 or md:w-3/12.
Then, purgecss will go through the css file, look at each selector in it and simply look if the selector is also in the content files. If it's not, the css is removed. In this example with the default extractor, w-6/12 and md:w-3/12 will be removed.

Thanks for explaining and trying to help. However I still couldn't get the extractor to work. I still can't get it to work properly. LOL

What I am trying to do here is to get PurgeCSS to read not allow both of the following classes to pass:
.scss

.flexgrid {
  @apply .styleA;

  & > *[class*=w-] {
    @apply .styleB
  }
}

Because the usage of this is just simply using the .flexgrid on any div and no extra classes is set to its child.
.html

<div class="flexgrid">
  <div class="">Content<div>
  <div class="">Content<div>
<div>

So with this html, the extractor will only pick up the flexgrid class. And after comparing it with the css file above, only .flexgrid {} gets through. The one with a child selector gets removed.

So the question is how do I get PurgeCSS to support custom css selectors such as the css example above?

Thanks for the clarification. I understand the problem now.
Purgecss does not behave as expected with attribute selectors. It should leave the attributes selectors in the css. I will look into it and release a new version when the issue is fixed

The issue should be fix in v0.14.0. Let me know if you found any issues with it.

Will this only work under legacy: true? In my tests, the legacy option will not read numbers and some symbols and is quite inaccurate. The PurgeCSS (non-legacy) option is much more accurate and I think this bug should be fixed for both legacy and without (preferably).

What do you think?

It should work for both.
The legacy option was meant to provide a similar result as purifycss when purgecss was in an early stage. The option will be removed with the 1.0.0 version.

Hmm, tested it and somehow it didn't work unless legacy: true is set.

.flexgrid {
  @apply .flex .flex-wrap .-mx-4 .-mb-8;

  & > *[class*='w-'] {
    @apply .px-4 .pb-8
  }
}

Output

.flexgrid{display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-left:-1rem;margin-right:-1rem;margin-bottom:-2rem}@supports(display:-ms-grid){}

The test in the test folder had legacy: true set I think.

There are tests for both with and without legacy.
Could you create a repo that reproduce the issue? It will be easier for me to look at the issue that way.

Hey @Ffloriel. Here's the repo. I hope I did it correctly, I used gulp instead of webpack.
https://github.com/pxwee5/test-purgecss/

@pxwee5 thank you very much.

_gulp-purgecss_ was still using the v0.13.0. _gulp-purgecss_ version is now aligned with purgecss.
The output is

.flexgrid {
  background-color: black
}

.flexgrid[class*=w] {
  background-color: blue;
}

.flexgrid>*[class*=w-] {
  background-color: yellow;
}

Gah. That was it! Didn't know I have to upgrade the bundler plugins as well.
Working great now! Thanks alot for the prompt replies and everything. Really appreciate the support.

Was this page helpful?
0 / 5 - 0 ratings