Using PurgeCSS with Joomla 4
The job of PurgeCSS is to help you to remove unused CSS from bloated stylesheets. I say help you, because it is not intended for use as an automated tool that just works out of the box. It requires human intervention and common sense to get the most out of it.
So how does it work with Joomla? And in particular Joomla 4? There's no documentation on the PurgeCSS site on how to use it with Joomla, and no plugins written for it either.
But don't despair - using PurgeCSS with Joomla is easier than it looks.
What PurgeCSS does
PurgeCSS is really useful if you're using a CSS framework. The figures in the tables below come fromĀ CSS Auditors data (2022), and represent the minified file size of each CSS framework in it's full version.
CSS Frameworks
CSS Framework | Minified Size (kB) |
---|---|
Tailwind | 2930 |
Semantic UI | 628.29 |
Primer CSS | 591.74 |
Ant Design | 544.07 |
UI Kit | 256.01 |
CSS Frameworks (cont'd)
CSS Framework | Minified Size (kB) |
---|---|
Bulma | 205.62 |
Bootstrap | 163.82 |
Materialize | 139.62 |
Foundation | 134.84 |
Pure CSS | 16.79 |
These frameworks can generate a lot of classes that you don't actually use, and that's where PurgeCSS comes into it's own. It examines the content of your files (typically templates) looking for css class selectors. It then compares those to class selectors found in the css stylesheet you specify.
If a class in the css stylesheet has no match with the content examined, PurgeCSS can be used to remove that selector from the stylesheet. That sounds a bit nuclear, but the way it removes it is entirely up to you. You can have it print out those unused classes to the console, get it to create a brand new stylesheet with those unused classes totally removed or, indeed, remove them from your source stylesheet. Up to you.
There are 2 ways to run PurgeCSS:
- via CLI (terminal)
- via javascript file (with config file, optional task runner and/or plugins for your specific framework)
Using PurgeCSS CLI with Joomla 4
Good to know
- The Joomla 4 install I'll be referring to is not using Cassiopeia, but a stand-alone template which we'll call:
my_template
- The stylesheet for
my_template
was compiled from source files (scss) downloaded from Bootstrap. The point being we are not using any of Joomla's stylesheets for the template
We'll be using the CLI method because it's fast, readable and avoids us having to write a dedicated module or plugin (or pay for one!). To use the CLI, we'll need to install purgecss globally. Open a terminal and enter:
npm i -g purgecss
Second thing is to understand the main options for using the CLI to run PurgeCSS. The ones I'll be using for a Joomla 4 install using the Bootstrap css framework are:
- content
- The files to examine to find
class
selectors (typically templates) - css
- The stylesheet that PurgeCSS will compare to the class selectors found in content specified above
- variables
- Frameworks like Bootstrap include variable definitions. You can remove unused variables with this option
- safelist
- classes that will not be removed by PurgeCSS
- output
- name/location of the new 'purged' css file. If not specified, will default to std out (terminal)
Building the CLI Command
Content option
Template Files
In this Joomla install the default template is at templates/my_template/
. The only files in the root of this folder are the 3 template files - index.php, error.php, and component.php. Here's how the content option would look to get PurgeCSS to scan our template files:
--content templates/my_template/*.php
Template Override Files
If you've overridden templates for any plugins, modules, layouts or components, these will be in the templates/my_templates/html/
folder. So we can use a glob pattern to have PurgeCSS scan any php files in the html folder, including sub-folders. We'll add this as follows:
--content templates/my_template/*.php
templates/my_template/html/**/*.php
** means recurse into subfolders
Default Plugins, Modules, Layouts, Components
You might also be using some default templates - meaning you have no template overrides for these particular plugins, modules, layouts or components. In this Joomla 4 install we'll be using the default templates for the following:
- mod_breadcrumbs
- com_finder
- Layout - pagination
- Plugins - Content - Page Navigation
We'll get PurgeCSS to checkout the templates for those as follows:
--content templates/my_template/*.php
templates/my_template/html/**/*.php modules/mod_breadcrumbs/tmpl/*.php components/com_finder/tmpl/search/*.php layouts/joomla/pagination/l?.php
plugins/content/pagenavigation/tmpl/*.php
l?.php will find link.php, links.php and list.php but not xlinks.php
Javascripts
There is CSS injection from a javascript file in my_template
, so we'll have PurgeCSS check that out too:
--content templates/my_template/*.php
templates/my_template/html/**/*.php
modules/mod_breadcrumbs/tmpl/*.php
components/com_finder/tmpl/search/*.php
layouts/joomla/pagination/l?.php
plugins/content/pagenavigation/tmpl/*.php media/templates/site/my_template/js/injectcss.js
CSS option
I'm going to refer PurgeCSS to the unminified stylesheet for readability. You can use the minified file too, it makes no difference.
--css media/templates/site/my_template/css/bootstrap.css
Variables option
Since Bootstrap specifies a large number of variables in the code (eg --bs-border-radius-lg
, --bs-pink
) we'll ask PurgeCSS to remove them if they're not being used. The default is not to remove them.
--variables true
Safelist option
I have one class in the stylesheet that I haven't finished styling yet: mycookiebanner
. I'll finish it once I've decided what cookie banner I'll install. I don't want PurgeCSS to strip this out for now.
--safelist mycookiebanner
After I ran PurgeCSS, I discovered that Bootstrap's js was injecting a class when a modal was triggered. PurgeCSS couldn't discover that since the Bootstrap js was being imported from a CDN. So, new safelist for future runs of PurgeCSS on this Joomla install:
--safelist mycookiebanner modal-backdrop
Output option
I want PurgeCSS to output it's results to a new stylesheet that I can test with the install called: purged.css
. This stylesheet will have all unused class selectors and variables stripped out. I'll put that into the same folder as my template's css for ease of testing:
--output media/templates/site/my_template/css/purged.css
All together now
I opened a terminal in the root folder of the joomla 4 install and entered the following to have PurgeCSS do it's thing:
purgecss --content templates/my_template/*.php templates/my_template/html/**/*.php modules/mod_breadcrumbs/tmpl/*.php components/com_finder/tmpl/search/*.php layouts/joomla/pagination/l?.php plugins/content/pagenavigation/tmpl/*.php media/templates/site/my_template/js/injectcss.js --css media/templates/site/my_template/css/bootstrap.css --variables true --safelist mycookiebanner modal-backdrop --output media/templates/site/my_template/css/purged.css
In the previous examples I put the code on separate lines for readability. You don't need to do that in the CLI.
Results
I tested this visually, and found around 20 missing class selectors. Apart from the missing modal-backdrop
css class injected by Bootstrap, the rest had been entered into articles using a text editor. Because they were in the database (content and modules tables, respectively), PurgeCSS had no access to them.
Once I added those to the safelist, PurgeCSS was able to reduce the original 285kB bootstrap.css file to 90kB, and on minification, we ended up at 74kB. Great job PurgeCSS! Anything under 100kB works for me.
Other Approaches
Rejected CSS
It's worth mentioning that PurgeCSS can also output the rejected classes only. This is pretty useful in certain situations. To do this, omit the --output path/to/purged.css
and replace that with:--rejected true
(output to console)--rejected-css path/to/your/rejected.css
(output to file)
Using a Script
The Script method can be used in conjunction with the CLI for Joomla 4. This not only preserves the safelist in a file, but allows you to use regex with the safelist as well. The safelist can be divided into standard (as used with CLI), deep, greedy and variables arrays (see how to use them in the PurgeCSS documentation). I've provided a bare bones outline on how to set it all up here.
- Create a config file called:
purgecss.config.js
. Put it wherever you like, but just remember that file paths must be relative to it's location. I put mine into the root of themedia/templates/site/my_template
folder. And it can stay there, for future use. - Run PurgeCSS as follows:
purgecss --config path/to/purgecss.config.js --output path/to/purged.css
Notice we've added a blocklist meaning: these classes are never to be included.
Sample purgecss.config.js
module.exports = { content: ['path/to/content/1', 'path/to/content/2'], css: ['path/to/stylesheet'], variables: [true], safelist: { standard: [/accordion/,'badge','kbd'], deep: [/show$/], greedy: [/^modal/], variables: ['--bs-blue','--bs-btn-disabled-bg'] }, blocklist: [/^navbar/, /blockquote-footer/] }