purgecss can't recognize conditional classes
Asked Answered
T

5

17

So I'm using TailwindCSS for a WP theme I'm developing.

I ran into an issue in creating the production grade theme files because, from how I understand the problem, purgecss can't recognize conditional classes used on template parts. For example, let's say I created a template part called "business-card.php" where I pass it a variable type (using set_query_var / get_query_var):

page-about.php

set_query_var('type', 'A');
get_template_part('template-parts/content/business', 'card');

set_query_var('type', 'B');
get_template_part('template-parts/content/business', 'card');

businesss-card.php

$type = get_query_var('type')
<div class="<?php echo type == 'A' ? 'text-color-A' : 'text-color-B' ?>">
--- insert some content here ---
</div>

So there will be two divs, one will have a text-color-A class, the other will have a text-color-B, both were created using a config file(rather than included in the base tailwind theme). This is fine in development -- since tailwind does actually create the utility color classes from the config file. But for some reason, when it's in production (i.e. purged & minified), it doesn't have those utility classes -- which were only used in the template part as conditional classes (and not in any other file).

Thorma answered 19/4, 2020 at 22:59 Comment(1)
For Nextjs 13.4+ refer https://mcmap.net/q/237148/-dynamically-build-classnames-in-tailwindcssCeladon
H
20

PurgeCSS is intentionally very naive in the way it looks for classes in your HTML. It doesn't try to parse your HTML and look for class attributes or dynamically execute your JavaScript — it simply looks for any strings in the entire file that match this regular expression:

/[^<>"'`\s]*[^<>"'`\s:]/g

That means that it is important to avoid dynamically creating class strings in your templates with string concatenation, otherwise PurgeCSS won't know to preserve those classes.

So do not use string concatenation to create class names:

<div :class="text-{{ error ? 'red' : 'green' }}-600"></div>

Instead, dynamically select a complete class name:

<div :class="{{ error ? 'text-red-600' : 'text-green-600' }}"></div>

As long as a class name appears in your template in its entirety, PurgeCSS will not remove it.

See the docs for more details:

Hayman answered 30/4, 2020 at 23:32 Comment(4)
You should mention the Tailwind link source where you copied the text from TailwindCSS / Writing purgeable HTML.Apuleius
@ChristosLytras I used to have that there... don't know why I removed it. Added back, thanks!Hayman
Interesting. You can even put tailwind classes in a comment to prevent purging.Mccants
Isn't the OP emitting full class names in their php?Determinism
M
9

If you are using Tailwind 2.0+ you can configure whitelisted classes that will be ignored by purge CSS directly inside of your tailwind.config.js file.

An example of my own code where I whitelist the class text-ingido-400 can be seen below

  // tailwind.config.js
  module.exports = {
    purge: {
      content: ['./src/**/*.{js,jsx,ts,tsx}', './public/index.html'],

      options: {
        safelist: ['text-indigo-400']
      }
    } ,
     darkMode: false, // or 'media' or 'class'
     theme: {
       extend: {},
     },
     variants: {
       extend: {},
     },
     plugins: [],
   }

For more information you can check out the relevant documentation located at: https://tailwindcss.com/docs/optimizing-for-production

Minnieminnnie answered 19/2, 2021 at 9:52 Comment(1)
safelist is directly at the same level as content in the config.Gag
O
6

You can use the PurgeCSS whitelist option to add those classes.

const purgecss = new Purgecss({
    //... Your config
    whitelist: ['text-color-A', 'text-color-B', 'etc']
})

Or the whitelistPatterns (Regex match)

whitelistPatterns: [/^text-color/], // All classes starting with text-color

You can find more information here

Owades answered 20/4, 2020 at 0:37 Comment(1)
I believe whitelist is deprecated. safelist does accept both complete strings and regex with some additional options: purgecss.com/safelisting.htmlMediocre
C
0

If you define your class names in a variable above where you want to use them it works akin to safe listing them in Tailwind or whitelisting them in PurgeCSS, is potentially easier to maintain, and works good in a pinch if you have a small number of possbile dynamic class names.

var classes =`grid-cols-1 grid-cols-2 grid-cols-3 grid-cols-4`
    return (
               <div className={`grid grid-cols-${items['grid-cols']}`}>
                
               </div>
           )
Carolann answered 31/1, 2022 at 21:14 Comment(0)
M
0

For some tailwindcss class, you can use inline style instead.

Inline style allow you to use dynamic value, like <div style="padding-left:{indent}rem">.

I think it works in php also. More details can be found here

Mat answered 29/4, 2022 at 9:12 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.