Recently, while writing up some examples and pattern for using htmx with Django for form validation, I discovered a new trick for using externally defined CSS without having to change the HTML you are working with.
To make it concrete, an example might be that you are using some CSS from a CSS library or framework that requires your HTML to look a certain way. In the Bulma framework, for instance, you have to add the right
class attribute directly on an element that needs styling.
At the same time, you might be working with another system that is generating the HTML for you, and modifying that output might be hard or impossible or just tedious and a potential maintenance burden going forward. For instance, in Django forms, there is an ErrorList class whose output can be overridden, but by default renders like this:
Now I have these requirements:
I want this error list to be coloured using a Bulma colour utility as if it had
class="has-text-danger"when it appears within a field row (which are
When it appears at the top of the form where it has an extra
nofieldclass, I want it to instead be styled like a Bulma notification as if it had
class="notification is-danger is-light".
But I want to do these without changing the HTML we’re given by Django, or changing existing CSS – only by adding some CSS rules.
The “best” way to do this is if your CSS framework provides its styles as a set of Sass mixins, or something equivalent. Bulma, as it happens, usually does this, but sometimes we’re not so lucky, and we just have CSS.
The trick I learnt requires you to use Sass/SCSS and the @extend directive. This powerful directive takes rules relating to one selector, and pulls them into whatever rule you are writing.
(If you are, like me, put off using things like CSS pre-processors because of the need for a separate build step, or needing to use Node.js/npm, see my post on How to use Sass/SCSS in a Django project without needing Node.js/npm or running a build process)
The one thing you have to do is rename the base CSS file you want to re-use from
.scss. This works because SCSS is a CSS superset. Then, for the example above, you can write your own SCSS file like this:
This technique can be very powerful e.g. make all
input[type=text] inside a
<form class="bulma"> have the normal Bulma input appearance:
This will include all related rules like
As mentioned, it may not always be the best technique, but it’s a great one to have in your toolbox.