tailwind-csstailwind-css-4

How is it possible to specify a safelist in TailwindCSS v4? Is it possible to list patterns and variants instead of full class names?


How to make a safelist in TailwindCSS v4?

As of now tailwind v4 preferable configuration is to use CSS. Not a .config.js anymore. But even if I use the JS-based configuration, the safelist property is already disabled in it and can no longer be used from v4 onwards.

In v3 in a file tailwind.config.js we could do:

export default {
  safelist: [
    {
      pattern: /grid-cols-+/,
      variants: ["sm", "md", "lg", "xl"],
    },
  ],
}

Now my workaround is to use a dummy-styled, invisible html or combinations of CSS styles with @apply sm:grid-cols-1 sm:grid-cols-2 lg:grid-cols-1... etc. Unfortunately this is what my UI and user options are done.

Have they dropped this feature? Can this be done "easly" in the TailwindCSS v4?


Solution

  • TLDR: The v3 safelist mentioned in the question can be written as follows starting from v4.1.

    Values can be written comma-separated within curly braces. In v3, grid-cols ranged from 1 to 12; from v4 onwards, it goes up to infinity. Including an infinite number of values in the compiled CSS would be madness, as it would drastically increase the size of the compiled CSS; so from 1 to 12, it would look like this:

    @source inline('{sm:,md:,lg:,xl:,}grid-cols-{1,2,3,4,5,6,7,8,9,10,11,12}');
    

    Note: Since there are variants, a comma indicates that we also want the plain class name version. So, request grid-cols-{1..12} even without a variant. If we don't add a comma after sm, md, lg, or xl, then the plain version won't be included in the compiled CSS, only the sm, md, lg, and xl variants will be.

    A new syntax has been introduced that makes it easy to list numbers. This uses another pair of curly braces, where you specify the start and end points, and as a third value, the step size. For example, {100..900..50} means that you want every number from 100 to 900 in steps of 50; i.e., 100, 150, 200... 850, 900.

    @source inline('{sm:,md:,lg:,xl:,}grid-cols-{{1..12..1}}');
    

    When requesting a range, if the third value is omitted, the list is automatically interpreted with a step of 1; so this is also sufficient:

    @source inline('{sm:,md:,lg:,xl:,}grid-cols-{{1..12}}');
    

    This can actually be made more complex, since I can request fixed numbers as well as different ranges. For example, I can request the value 1 explicitly, and then ask for values from 10 to 90 in steps of 5, and so on:

    @source inline('{sm:,md:,lg:,xl:,}grid-cols-{1,{10..90..5}}');
    

    From TailwindCSS v4.1.0 owards

    With this feature, now have the ability to include critically important classes in the compiled CSS using a syntax similar to the safelist property from v3.

    How to can use

    With @source, can provide file paths by default; specifying files where TailwindCSS classes are used. This instructs TailwindCSS to scan those files, collect all the class names have used, and include them in the compiled CSS.

    With @source inline, instead of specifying a file path, can directly pass in specific class names. It's as if had used them in a file, but even without actual usage, request that they be included in the compiled CSS. For the class names provided here, a special syntax is available—already familiar from v3—that allows us to list variants and specify variable parts of the class names.

    Here's an example from the PR to illustrate the inline syntax:

    @source inline('underline');
    

    For more complex syntax:

    @source inline('{hover:,}bg-red-{50,{100..900..100},950}');
    

    In this example, request both the plain class names and the hover: variant versions. Also ask for the bg-red colors: 50, followed by every 100-level value from 100 to 900, and finally 950.

    Each class name must be passed through a separate @source inline. So, for example, as mentioned earlier, the underline and bg-red class names should be declared as two separate @source inline statements to ensure they are included in the compiled CSS, regardless of whether they are actually used anywhere.

    For example, you can also generate the pt-, pb-, pl-, pr-, px-, and py- classes with a single @source inline declaration in a similar way from 1 to 10 (stepping by 1 when the third value is omitted):

    @source inline("p{x,y,t,b,l,r}-{1..10}");
    

    Note: Here, I didn't add a comma at the end of the x,y,...,l,r list; but if I did, it would also generate the p-1, p-2 classes.

    But we can make this even more complex by declaring margin and padding together:

    @source inline("{m,p}{x,y,t,b,l,r}-{1..10}");
    

    Note: You can see that I didn't add a comma at the end of the m,p list to avoid declaring meaningless plain x-1, y-2, ... classes.

    Use carefully

    I'd like to point out that excessive use of the safelist is not a good idea. Handle the safelist with great care and only use it in absolutely necessary cases in order to reduce the size of your compiled CSS. A bloated compiled CSS will worsen the loading experience and demand more data usage from every visitor.



    Until TailwindCSS v4.0.17

    Safelists and blocklists — can't force Tailwind to generate certain classes or prevent it from generating other classes yet.


    Source: Open-sourcing our progress on Tailwind CSS v4.0

    As of version 4.0, there is no built-in option for using the safelist feature available in v3. However, as others have suggested, if you can reference the required class names in some form, TailwindCSS will include them in the build.