I’ve been hearing a lot about Tailwind CSS lately and I wanted to give it a try, but I wanted to combine Tailwind with Create React App. In this post I’ll show you how to use Create React App with Tailwind CSS in just a couple quick minutes.
I’ll show two versions: a Basic one that has the most minimal setup, and a Production version that will set things up for an optimized workflow and a smaller production build.
Here’s how to integrate Tailwind with CRA, without ejecting. It’ll work like this:
- We’ll install a tool to do the build
- A new build step will call our tool and to generate the CSS to use Tailwind
- We import the generated CSS file into our React app
What’s Tailwind CSS?
Tailwind is a low-level CSS framework created by Adam Wathan. Their site calls it “A utility-first CSS framework for rapidly building custom designs.”
The idea behind Tailwind is that it gives you a bunch of utility classes, like text-lg
(for a large-ish font size) or mx-auto
as a shorthand for auto margins in the X direction, useful for centering something horizontally (short for margin-left: auto; margin-right: auto;
).
You apply these utility classes directly to your HTML or JSX elements (via the className
prop if you’re using React).
Not everyone loves this idea. But some people absolutely do love Tailwind and talk about how productive it has made them. I think it’s worth a try.
(If the idea of adding such low-level classes to your HTML bothers you, check out In Defense of Utility First CSS by Sarah Dayan and have a look at the screencast tutorials that Adam created. They might change your mind.)
Start With a React project
We’ll be modifying a Create React App (CRA) project, so create a new one or use one you already have. The steps after this will work fine with an existing project.
Set Up the Build
I’ve got two versions for you. Basic and Production.
Choose Basic if you just want to try out Tailwind with React, don’t plan on deploying this app, and want the most minimal possible setup. It’ll require a dev server restart any time you change the tailwind.css
file, but if you’re doing things the Tailwind Way (adding classes to elements instead of writing CSS), you won’t really be changing that file anyway.
Choose Production if you want something you can deploy. This incorporates PurgeCSS to make sure your production builds are as tiny as possible, and a live rebuild that watches for changes. The tradeoff is more configuration up front, but it’s still just a few packages and lines to copy into place.
Setup a Basic Tailwind + CRA Build
1. Install Tailwind
Tailwind comes with its own CLI for doing a build, so we can just install the tailwindcss
package.
2. Add Tailwind to the Build
To avoid ejecting from Create React App’s build system we’re going to insert a step that builds Tailwind before the existing start
and build
scripts.
Open package.json
in the CRA project, add a script called build:tailwind
and two more called prestart
and prebuild
.
(if you haven’t modified your scripts, you should be able to copy/paste this verbatim)
"scripts": { "build:tailwind": "tailwindcss build src/tailwind.css -o src/tailwind.generated.css", "prestart": "npm run build:tailwind", "prebuild": "npm run build:tailwind", "start": "react-scripts start", "build": "react-scripts build", "test": "react-scripts test", "eject": "react-scripts eject" }
The build:tailwind
script will compile our src/tailwind.css
file, and output src/tailwind.generated.css
– which our app will then import
.
We’re effectively saying “build Tailwind before starting up dev mode” and “build Tailwind before building the React app for production”.
(Note: The script name build:tailwind
isn’t special. You could call it build:css
or awesomeness
or happydays
if you wanted.)
NPM supports pre- and post- scripts
Fun fact: Scripts that start with the word “pre” are special to NPM (and Yarn). They automatically run before the named script.
Here, prestart
will run before the start
script. When you run npm start
, NPM will run both automatically.
The prefix “post” will do the same kind of thing, but will run after the named script. (e.g. postbuild
would run after build
is finished)
A One-Time Build
This setup will only build the CSS once, at startup. It will not watch for changes.
If you change src/tailwind.css
you’ll have to restart the development server. If you need automatic rebuilds, check out the Production setup below.
3. Set up the Tailwind source CSS file
(this step is the same as in the Production setup)
You probably noticed that our build step refers to a src/tailwind.css
file. Create that now, and paste this in:
@tailwind base; @tailwind components; @tailwind utilities;
The Tailwind PostCSS plugin will replace these @tailwind
directives with Tailwind’s generated CSS and write it out to src/tailwind.generated.css
(that name is decided by the build:tailwind
script we added to package.json
).
4. Import the Generated CSS File
(this step is the same as in the Production setup)
At the top of your index.js
file, import the tailwind.generated.css
file that’s being generated by Tailwind.
Then we can try out a few Tailwind classes to make sure it works.
import React from 'react'; import ReactDOM from 'react-dom'; import './tailwind.generated.css'; const App = () => ( <div className="max-w-md mx-auto flex p-6 bg-gray-100 mt-10 rounded-lg shadow-xl"> <div className="ml-6 pt-1"> <h1 className="text-2xl text-blue-700 leading-tight"> Tailwind and Create React App </h1> <p className="text-base text-gray-700 leading-normal"> Building apps together </p> </div> </div> ); ReactDOM.render(<App />, document.querySelector('#root'));
Start up the development server as usual with npm start
.
That’s all there is to it!
Where to Make Changes
Don’t change tailwind.generated.css
since your changes will be wiped out the next time you start up the dev server or run a production build. Instead, put changes in src/tailwind.css
and restart the server/re-run the build.
I’d probably avoid committing tailwind.generated.css
to source control since it’s a generated file.
Production Tailwind + CRA Build
1. Install Tailwind and Tools
We need Tailwind itself, and a couple tools to build it – namely, PostCSS and the autoprefixer plugin, along with npm-run-all to run the file watcher and PurgeCSS to minify our build output.
Install ‘em all at once.
npm install tailwindcss postcss-cli autoprefixer npm-run-all @fullhuman/postcss-purgecss
2. Create a PostCSS config file
PostCSS is a tool for building CSS. It supports using a variety of plugins to customize the process, and here we’ll be using Tailwind as a plugin along with autoprefixer (for browser compatibility) and PurgeCSS (for a smaller output file).
Create a file called postcss.config.js
in the root of your CRA project, and paste this in:
// postcss.config.js const purgecss = require('@fullhuman/postcss-purgecss')({ // Specify the paths to all of the template files in your project content: [ './public/**/*.html', './src/**/*.js', // etc. ], // Include any special characters you're using in this regular expression defaultExtractor: content => content.match(/[\w-/:]+(?<!:)/g) || [] }) module.exports = { plugins: [ require('tailwindcss'), require('autoprefixer'), ...process.env.NODE_ENV === 'production' ? [purgecss] : [] ] }
This file is from the Tailwind docs, and I suggest reading that linked section for more on what the defaultExtractor
regex does and some guidelines for writing your JSX/HTML.
With this in place, we can run the postcss
command, which will in turn call Tailwind, and out will pop our generated Tailwind file. And in production build mode (when you run npm run build
), PurgeCSS will strip out unused CSS classes.
3. Add a Step to the Build
To avoid ejecting from Create React App’s build system we’re going to modify package.json
so that the npm start
command will run both the PostCSS build and the CRA server.
The run-p
command (run in parallel) that comes with the npm-run-all package is the secret sauce here.
Update the scripts
section of package.json
to look like this. (unless you’ve customized your scripts, you should be able to copy/paste this verbatim)
"scripts": { "build:tailwind": "postcss src/tailwind.css -o src/tailwind.generated.css", "watch:tailwind": "postcss -w src/tailwind.css -o src/tailwind.generated.css", "start": "run-p watch:tailwind start:react", "start:react": "react-scripts start", "prebuild": "npm run build:tailwind", "build": "react-scripts build", "test": "react-scripts test", "eject": "react-scripts eject" },
We have build:tailwind
and watch:tailwind
scripts that are largely the same, except we’re passing the -w
flag in watch mode.
(Note: The script name build:tailwind
isn’t special. You could call it build:css
or awesomeness
or happydays
if you wanted.)
Then, we renamed the existing start
script to start:react
so that we can add our own start
script.
Our start
script will run the watch:tailwind
and start:react
scripts in parallel. CRA and PostCSS co-existing harmoniously.
After you make these changes, start everything up with npm start
and try changing src/tailwind.css
. PostCSS will detect the change, write out a new src/tailwind.generated.css
file, then CRA will detect that change and rebuild the React app, and the browser should refresh. Phew.
It’s a bit of a Rube Goldberg machine, but then again, so are most builds :)
NPM supports pre- and post- scripts
Fun fact: Scripts that start with the word “pre” are special to NPM (and Yarn). They automatically run before the named script.
Here, prebuild
will run before the build
script. When you run npm run build
, NPM will run both automatically.
The prefix “post” will do the same kind of thing, but will run after the named script. (e.g. postbuild
would run after build
is finished)
4. Set up the Tailwind source CSS file
(this step is the same as in the Basic setup)
You probably noticed that our build step refers to a src/tailwind.css
file. Create that now, and paste this in:
@tailwind base; @tailwind components; @tailwind utilities;
The Tailwind PostCSS plugin will replace these @tailwind
directives with Tailwind’s generated CSS and write it out to src/tailwind.generated.css
(that name is decided by the build:tailwind
script we added to package.json
).
5. Import the Generated CSS File
(this step is the same as in the Basic setup)
At the top of your index.js
file, import the tailwind.generated.css
file that’s being generated by PostCSS and Tailwind.
Then we can try out a few Tailwind classes to make sure it works.
import React from 'react'; import ReactDOM from 'react-dom'; import './tailwind.generated.css'; const App = () => ( <div className="max-w-md mx-auto flex p-6 bg-gray-100 mt-10 rounded-lg shadow-xl"> <div className="ml-6 pt-1"> <h1 className="text-2xl text-blue-700 leading-tight"> Tailwind and Create React App </h1> <p className="text-base text-gray-700 leading-normal"> Building apps together </p> </div> </div> ); ReactDOM.render(<App />, document.querySelector('#root'));
Start up the development server as usual with npm start
.
That’s all there is to it!
Where to Make Changes
Don’t change tailwind.generated.css
since your changes will be wiped out the next time you start up the dev server or run a production build. Instead, put changes in src/tailwind.css
and restart the server/re-run the build.
I’d probably avoid committing tailwind.generated.css
to source control since it’s a generated file.
Customize Tailwind
Tailwind has a bunch of good defaults. Nice set of colors. Good array of font sizes. Logical naming of classes. You definitely don’t need to configure anything out of the box. But if you want to customize it, you’ll need a tailwind.config.js
file.
To create it, run npx tailwind init
for a minimal config, or npm tailwind init --full
for a complete config that you can tweak.
Tailwind will automatically pick up on that file, so we don’t need to change anything about our build.
Learn More About Tailwind
Hopefully this post got you up and running with Tailwind CSS. To learn more, check out their excellent documentation, and especially the screencasts that Adam put together. It was really helpful for me to see how he used Tailwind in practice, and the videos cover a lot of common things you’d want to build like card layouts, badges, navbars, and dropdown menus.
Using Tailwind CSS with Create React App was originally published by Dave Ceddia at Dave Ceddia on March 30, 2020.
CodeProject