Setting up Tailwind CSS with Flask
Recently, I have decided to switch from Tachyons to Tailwind and while I really like Tailwind and the ecosystem around it, setting it up in my Flask project was quite a pain for me. I guess it's fairly simple if you are a front end developer and have some CSS build system in place but I was using no such thing and was simply importing all CSS libraries using the link tag. And while it's possible to import Tailwind using the link tag, most of the stuff that makes it so powerful, such as customization, is only possible when using a proper build pipeline.
Set up your Flask app
We will be using Flask-Assets to manage our assets pipeline so let's first install it.
pip install Flask-Assets
Next, let's install Tailwind, PostCSS (a CSS preprocessor used by Tailwind), Autoprefixer and PurgeCSS.
npm install tailwindcss postcss-cli autoprefixer @fullhuman/postcss-purgecss
Now, in your Flask app, let's create a CSS bundle that will take all source CSS files and processes them using PostCSS.
from flask_assets import Environment, Bundle
assets = Environment()
assets.init_app(app)
css = Bundle('src/css/*.css', filters='postcss', output='dist/css/main.css')
assets.register('css', css)
Set up PostCSS
The tricky part was setting up the PostCSS (using the postcss.config.js
file) because for some reason webassets
(which is used internally by Flask-Assets) changes its working directory when executing postcss
binary and executes it inside the directory where the currently processed CSS file is. PostCSS is able to find your postcss.config.js
(which is typically in the root directory of your project) by walking up the directory until it finds one but Tailwind expects its config file (tailwind.config.js
) to be in the current working directory by default so you have to explicitely tell it where to find it.
That's why we have to set all paths relative to the postcss.config.js
file (using __dirname
variable) instead of relative to the current working directory.
Below is our final postcss.config.js
:
const path = require('path');
module.exports = (ctx) => ({
plugins: [
require('tailwindcss')(path.resolve(__dirname, 'tailwind.config.js')),
require('autoprefixer'),
ctx.env === 'production' && require('@fullhuman/postcss-purgecss')({
content: [
path.resolve(__dirname, 'templates/**/*.html')
],
defaultExtractor: content => content.match(/[A-Za-z0-9-_:/]+/g) || []
})
]
})
Also, note that in production we use PurgeCSS to remove all unused CSS classes by scanning all HTML templates in your project.
Set up Tailwind CSS
Finally, let's customize Tailwind using the tailwind.config.js
file (in your project root) to see that all is set correctly.
const defaultTheme = require('tailwindcss/defaultTheme')
module.exports = {
future: {
// removeDeprecatedGapUtilities: true,
// purgeLayersByDefault: true,
},
purge: [],
theme: {
extend: {
fontFamily: {
sans: ['Inter var', ...defaultTheme.fontFamily.sans],
},
},
},
variants: {},
plugins: [
require('@tailwindcss/ui'),
],
}
If you have any comments, feedback or questions, let me know on Twitter or via email.
Thanks for reading
If you liked the post, subscribe to my newsletter to get new posts in your mailbox! 📬
Also, feel free to buy me a coffee. ☕️