Configuring CSS Global Variables with Tailwind
I really wanted to use Framer Motion to do some easy color transitions on my site, but in order to change colors I need access to global variables. Luckily, there is a way to turn Tailwind's colors into global variables, or to even turn your own system color design into variables!
Let's dive in!
This is going to be a very simple process and we don't need any packages for this. In the Tailwind config file, we are going to import Tailwind's flattenColorPalette function like so:
const { default: flattenColorPalette, } = require('tailwindcss/lib/util/flattenColorPalette')
module.exports = {
...
}
Next we are going to use this function/ plugin to add each TW color as a global CSS variable:
module.exports = {
...everything_else,
theme: {
extend: {
colors: {
'primary-black': '#0c0b1d',
},
},
},
plugins: [addVariablesForColors],
}
// This plugin adds each Tailwind color as a global CSS variable, e.g. var(--gray-200).
function addVariablesForColors({ addBase, theme }) {
let allColors = flattenColorPalette(theme('colors'))
let newVars = Object.fromEntries(
Object.entries(allColors).map(([key, val]) => [`--${key}`, val])
)
addBase({
':root': newVars,
})
}
And just like that we now have global CSS Variables available to us!!
Extra: In another article I was showing how to use Jotai as my state manager to change the theme of the site.
Here, I am going to show how to extend that to use Framer Motion to change the colors when I change the theme.
First, install framer-motion package and then import it into the Layout file:
import { motion } from 'framer-motion'
Next, we can wrap our div that we want to change the color for in a motion.div like so:
<motion.div>{children}</motion.div>
When I change the theme, I am going to animate the motion.div's colors
const [theme, setTheme] = useAtom(themeAtom)
return (
<motion.div
animate={{ backgroundColor: theme === 'dark' ? 'var(--primary-black)' :
'#fff' }}
>
<button
className="button my-4 w-max"
onClick={() => setTheme(theme === 'dark' ? 'light' : 'dark')}
>
toggle theme
</button>
</motion.div>
)
So, when I click that toggle theme button, I am not able to set the backgroundColor for the whole page! And, to give myself more control on the animation of that I want to use Framer Motion.
This line:
animate={{ backgroundColor: theme === 'dark' ? 'var(--primary-black)' : '#fff' }}
It allows us to change the color based on the state, and so easily! The only thing is that we couldn't have replaced var(--primary-black)
with bg-black
. That wouldn't have worked - we need to have access to Global CSS Variables to make that change. And that is why we added that plugin / function to our Tailwind Config file earlier!