Extend Tailwind colours with CSS custom properties.
My new favourite way to theme a site using Tailwind ideology.
Custom properties are also known as CSS variables. But the spec calls them custom properties so that's what I will call them in the rest of this post.
Themes
There are many ways to customise colors on a website, in the same way there are many ways to build the same layout for a website in multiple ways.
Making themes for a site, or skins that you can apply is not a new concept. But reaching back all the way to TW 1.0 I always found colour systems or building themes with it somewhat counter productive. So when I was re-designing my site I using TW 3, I wanted to explore the best way to make it possible to write better themes.
Source
If you check the Tailwind CSS docs there are many 'right' ways to do things, and I would agree on most of them. Adam Wathan has written a lot of CSS in his time so I take his opinion and try them in practice, and usually find them to be informed and useful, so I bring them into my workflow.
I wont pretend to have invented this method of theming, it's directly from the Tailwind docs. But I have put it into practice so I wanted to write about my specific use-case and a few thoughts about it.
My Implementation
Here is a quick tl;dr example I knocked up on Tailwind Play: https://play.tailwindcss.com/pzmv6El2cY?file=config
Note that in real world you would not set the theme using this checkbox :checked
and ~ div
sibling method but this is just to make it easy to switch between the 2 example themes in the playground.
Steps
- Extend the Tailwind colour palette and let it know that the colors are from css variables
- Set our base custom properties in the
:root
definition of our css file. - Override them on a per-theme basis by adding a class to the body (or html depending on your cascase or how you write other CSS)
Define the palette
In tailwind.config.js
define the color palette by extending theme.colors
:
theme: {
extend: {
colors: {
theme: {
bg: 'var(--bg)',
text: 'var(--text)',
accent: 'var(--accent)',
},
},
},
},
Set default values
in our CSS file set the default values for each custom property in the :root
element:
:root {
--bg: #8ECAE6;
--text: #1e3a8a;
--accent: #ef233c;
}
This will be the default colours and is a good way to do this even if you don't have a second theme just yet.
Override them with a custom class
.theme-inverted {
--bg: #1e3a8a;
--text: #ffffff;
--accent: #fb8500;
}
Even make Dark mode easily
@media (prefers-color-scheme: dark) {
:root {
--bg: #1e3a8a;
--text: #eef2ff;
}
}
Thoughts
So I really like this way of handling custom themes, and how it integrates with Tailwind. I did wonder about:
- What the best name for the colour paletter would be?
- what are the advantages / disadvantages of using this method rather than just extending palette by referencing an existing colour (eg blue-900) directly.
Palette Keyword Naming
- I initially thought the
theme
keyword as the name for the color palette would cause some issues but then I used it, and it works fine.
Advantages
- An added advantage I discovered is that if you have an inverted section you no longer need to make a new block of markup with darker versions of colors. You can just apply the
theme-invert
class to the div and css custom properties do the rest.
Disadvantages
- So far I did not experiment with RGB values in order to use opacity modifier as per the TW Docs. This may be an issue later on if I want to use
bg-theme-text/50
, but so far not encountered the need for this.