The 5.x version of the theme has the JIT (just in time) compiler enabled by default and whilst it can work using Twig files in your theme, it doesn't know about classes used within content that is stored within the database.
This is something that I've needed to solve in some of my own projects before too so there are a few options but I'd not recommend turning off the JIT compiler or PurgeCSS.
Adding classes to a safelist
The first option is to use the safelist option within the tailwind.config.js file:
Adding any classes to the safelist will force them to be generated, or prevent them from being purged, even if they are not found within the theme's templates files.
This is refered to within the Tailwind CSS documentation for safelisting classes:
One example of where this can be useful is if your site displays user-generated content and you want users to be able to use a constrained set of Tailwind classes in their content that might not exist in your own site’s source files.
Extracting the safelist to a file
In some projects, I found that I was adding a lot of classes to the safelist so I extracted the classes into a file instead.
Whilst it could be a JavaScript object that could be imported, as long as Tailwind sees the classes being used, the files just need to exist in a file that can be scanned - even just a plain text file called safelist.txt:
bg-red-500
text-3xl
lg:text-4xl
Rather than using the safelist, I can add the safelist file to content instead:
What we could also do is create the safelist file automatically based on the contents of the database using a custom Drush command.
Creating the command
This can be done by creating a new PHP class within a custom module and use the @command annotation to specify the command to run:
<?php
declare(strict_types=1);
namespace Drupal\opdavies_blog\Command;
final class ExportBodyValuesForThemePurgingCommand {
/**
* Drush command to export body field values into a file.
*
* @command opdavies:export-body-values-for-theme-purging
*/
public function handle(): void {
// ...
}
}
In this example, the file is modules/custom/opdavies_blog/src/Command/ExportBodyValuesForThemePurgingCommand.php.
Injecting the database service
It can now add it as a service within the opdavies_blog.services.yml file:
As we're going to need to query the database, I've added the database service as a dependency of my command and also created a constructor method and a property within the command class:
private Connection $database;
public function __construct(Connection $database) {
$this->database = $database;
}
Completing the handle method
As well as the database, I've added some properties to contain the table names to query as well as the name of the file to output:
Within the handle() method, I'm using an Illuminate Collection to loop over the array of tables, query the database, export the values, and write them into the file:
Now, when Tailwind CSS is run, it will find the exported body contents within the safelist file, and ensure that the appropriate classes are generated.
Was this interesting?
About me
I'm an Acquia-certified Drupal Triple Expert with 18
years of experience, an open-source software maintainer and Drupal core contributor, public speaker, live streamer, and host of the Beyond Blocks podcast.