CSS frameworks have become incredibly prevalent in web design over the years, with Google’s Material Design aesthetic gradually appearing throughout the web and Bootstrap’s library of plugins and themes becoming a popular default.
Good news is, the days of pages looking like this…

are long behind us, thanks in part to CSS frameworks.
But like many rebellious people, you may be asking, what can I use that’s not mainstream yet? Is there a better, more modern solution? Isn’t there something out there that doesn’t involve Google’s or Twitter’s participation at all?
Tailwind CSS, a new up-and-comer, is a framework that’s been making a name for itself since 2017. Tailwind was rated highest in satisfaction and interest by users from over 100 countries in both 2019 and 2020, as recorded by the State of CSS survey.

Tailwind provides a collection of pre-built utility classes, allowing developers to directly style HTML elements without needing to create CSS classes or write any CSS at all.
This lets Tailwind shine in its simplicity, flexibility, and available customization options. Unlike Material and Bootstrap, which provide opinionated pre-built elements (and which require a substantial setup and demanding syntax), Tailwind provides hassle-free access to styling CSS simply and quickly via utility classes.
If you’ve ever had a great idea for a frontend project, jumped straight into coding, and wanted to immediately flesh out that brilliant UI in your mind, Tailwind would allow you to style quickly before the inspiration left you, simply by slapping some of their utility classes on your markup.
In this article, we’ll be discussing how Tailwind works and the benefits and drawbacks of using it. We’ll examine the basic setup and workflow of Tailwind. Then we’ll look at implementing Tailwind with SASS or Styled Components, as well as building for responsiveness.
Let’s get on with it, shall we?
How does Tailwind work?
Utility Classes
Tailwind is a utility-first CSS framework. A utility class is a reusable CSS class that styles an element for a specific purpose.
Let’s say we’re expecting multiple elements to need a background color of blue. To create a utility class for this, we’d create a CSS class named bg-blue
and give it the style background-color: blue
. Now we can place our utility class bg-blue
onto the numerous HTML elements where the background needs to be blue.
With that concept understood, Tailwind essentially provides a huge collection of pre-built utility classes so you don’t have to create them yourself. It relies on stacking these classes onto HTML elements to fully style the element.
Using Tailwind, you may never need to write CSS. Instead, you’d just insert utility classes. For example, to easily create a button with rounded corners, a mild box shadow, and centered white text, you’d simply add the following utility classes to your element:
<button className="bg-blue-300 rounded-md shadow-md text-center p-8 text-white">
Button
</button>// NOTE: The examples in this blog will be referencing React components, hence the usage of "className".
That’s all you’d need to do to get a styled button that looks like this:

Tailwind provides hundreds if not thousands of utility classes, each with specific styling purposes. There is a class named .text-center
with a single CSS property of text-align: center
, another named .p-8
that has padding: 2rem
, and so on. This is how Tailwind works.
Benefits & Drawbacks
Pros
- The most apparent benefit to using Tailwind’s utility classes is it allows the developer to create their markup and style it at the same time without the need of creating CSS classes (or writing any CSS!). A developer using Tailwind would never need to leave their HTML or JSX code when building out views and components.
This can be especially beneficial if you’ve ever needed to put together a quick demo or MVP, or simply scaffold a UI to better visualize your project.
- An enormous perk provided by default is that Tailwind will automatically remove all unused CSS from the bundle sent to the browser. At build time, Tailwind will purge all unused CSS classes, creating the smallest CSS bundle your code can possibly provide, averaging at less than 10kb. This can dramatically improve page load times.
- As a styling framework, Tailwind is arguably less opinionated than other frameworks like Bootstrap and Material. Very often when using other frameworks, developers will find themselves rewriting the CSS provided by the framework to fully suit their needs.
- For more, see the differences between Tailwind CSS & Bootstrap.
Cons
- The initial learning curve of Tailwind can be unappealing, as you will inevitably find yourself returning to its docs to learn the correct utility class name. Something as traditional as setting
padding-top: 1rem
is nowpt-4
with Tailwind. In the beginning, this could potentially outweigh all the benefits Tailwind provides in regards to speed.
Once you’ve familiarized yourself with Tailwind, however, I guarantee you’ll find the utility class names to be as simple as remembering CSS attributes themselves.

- Though Tailwind is relatively unopinionated, the pre-built utility classes still have set values. For example,
text-red-300
is a utility class for text color with preset values for red, specificallyrgba(252, 165, 165, 1)
. Thankfully, these defaults can all be adjusted in atailwind.config.js
file to suit your needs. - By default, Tailwind doesn’t provide any styled components out of the box. All the components provided in a library like Bootstrap (for example, general navigation, buttons, headers) need to be implemented from scratch.
Tailwind Implementation & Workflow
To start off, you’ll want to install Tailwind with npm. To get the latest version and its peer dependencies, run npm install -D tailwindcss@latest postcss@latest autoprefixer@latest
.
If you’re going to customize some things, run npx tailwindcss init
to create the tailwind.config.js
file. This file allows custom implementation of styling, which we’ll discuss in the next section.
To inject Tailwind’s functionality, you will need a CSS file that includes these lines:
/* ./your-css-folder/styles.css */@tailwind base;
@tailwind components;
@tailwind utilities;
From here, you’re free to jump straight into coding.
Some things to keep in mind are the purpose and roadmap of your project. If you simply need something up and running with a deadline coming up, the basic implementation of Tailwind is fine.
If you know you’re going to be refactoring and potentially even removing Tailwind further down the road, be sure to pair your Tailwind code with SASS or Styled Component files.
Keeping these details in mind will foster a cleaner codebase, or a better transition into one.
Tailwind Config
Chances are you’re going to be customizing your Tailwind utility classes, because let’s be honest, their utility library doesn’t include everything. As an example, any kind of custom animation that isn’t a pulse or bounce will require a configuration.
To set this up, make sure to run npx tailwindcss init
. This will create a minimal tailwind.config.js
file in the root of the project.
Here, you can set whatever you might need that isn’t included by default in Tailwind, which may be custom fonts, animations, specific breakpoints, new utility classes, or adjusting Tailwind’s pre-built utility classes. Any custom styles here will take precedence over Tailwind’s existing classes.
//tailwind.config.jsmodule.exports = {
purge: ["./src/**/*.{js,jsx,ts,tsx}", "./public/index.html"],
darkMode: false, // or 'media' or 'class'
theme: {
extend: {
fontFamily: {
sans: [
"AvenirLTPro-Heavy",
"AvenirLTPro-Light",
"AvenirLTPro-Black",
],
body: ["AvenirLTPro-Medium"],
light: ["AvenirLTPro-Light"],
},
screens: {
xs: "320px",
sx: "420px",
},
colors: {
blue: {
lighter: "#3064b1",
light: "#CAE0FE",
DEFAULT: "#0E71FB",
dark: "#082959",
},
gray: {
lightest: "#F7FAFC",
lighter: "#EBEFF5",
light: "#E6EAF0",
DEFAULT: "#D7DBE0",
dark: "#6E6E6E",
darkest: "#333333",
},
},
animation: {
slideIn: "slideIn 200ms ease-in-out 1",
},
keyframes: {
slideIn: {
"0%": { transform: "translateX(-100vw)" },
"100%": { transform: "translateX(0)" },
},
},
Tailwind with Other Styling Packages
An obvious issue with Tailwind is the verbose class names that will eventually clutter your HTML or JSX. If we look at the previous example for the button, the full list of classes applied is bg-blue-300 rounded-md shadow-md text-center
. If we wanted to add more styling, we would need even more utility classes, making this line even longer.
And if every element were to look like this, the markup would become harder and harder to read.
const Name = () => {
return (
<div className="flex flex-col md:flex-row overflow-ellipsis overflow-hidden">
<div className="p-1 w-11r md:w-20r md:p-2 lg:w-29r inline-block text-gray-darkest font-sans flex items-center">
<h3 className="text-xs md:text-base overflow-ellipsis overflow-hidden xs:truncate md:overflow-clip md:whitespace-normal md:overflow-visible max-h-10">
{name}
</h3>
</div>
<div className="p-1 w-5r md:w-8r inline-block flex items-center justify-center">
<p className="text-xs md:text-base">
{date ? formatDate(date) : "Unspecified"}
</p>
</div>
</div>
);
};
Possible solutions to this problem involve pairing Tailwind with either SASS or Styled Components.
With SASS Using @apply
A common practice with Tailwind is to combine its usage with SASS/SCSS. A convention I’ve found useful is to limit the utility classes on any HTML element to 5 or 6. If an element requires further styling, you can use @apply
to style a SASS class using Tailwind utility classes, like so:
.card-body {
p {
@apply px-4 pb-4 text-lg pt-0 font-helvetica-neue text-center text-white
}
}
Then, you’re free to set this class wherever you need.
With Styled Components Using tw.macro
To use Tailwind alongside Styled Components, we’re going to need some extra dependencies, these being tailwind.macro
and babel-plugin-macros
. The combination of these two will allow Babel to read Tailwind utilities.
Once that’s done, you can start setting Tailwind utilities under className
in your styled components.
import styled from "styled-components";
import tw from "tailwind.macro";const AppStyles = styled.div.attrs({
className: "w-full h-screen flex flex-col items-center justify-center"
})`
h1 {
${tw`font-sans text-6xl text-teal-500`}
}
p {
${tw`text-lg text-gray-700`}
}
ul {
${tw`inline-flex mx-5`}
}
`;
For a more detailed implementation, check out these blogs by Ibrahima Ndaw and Derek Shanks.
Building for Responsiveness
Media Queries
One of the nice perks of using Tailwind is the simplicity of responsive styling. By default, Tailwind is mobile-first in regards to responsiveness. In other words, the breakpoints under the hood are specified using min-width
.
<button className="bg-blue-300 rounded-md shadow-md text-center p-8 text-white text-sm md:text-md md:p-10 lg:text-lg">
Button
</button>
In this example, the font-size
and padding
will change when the breakpoint for md
is reached, and the font-size
is enlarged even further when lg
the breakpoint is reached. To know the exact measurements for sizes like md
or lg
, you’ll have to refer to the Tailwind docs for the specific attributes. In regards to breakpoints, sm
is 640px
, md
is 768px
, and lg
is 1024px
by default. These can all be adjusted, and more sizes can be added, in the tailwind.config.js
file. For example, if you wanted md
to represent 800px
, you can change that in tailwind.config.js
.
// tailwind.config.js
module.exports = {
theme: {
screens: {
'sm': '640px',
// => @media (min-width: 640px) {...}
'md': '800px',
// => @media (min-width: 800px) {...}
'lg': '1024px',
// => @media (min-width: 1024px) {...}
'xl': '1280px',
// => @media (min-width: 1280px) {...}
'2xl': '1536px',
// => @media (min-width: 1536px) {...}
}
}
}
Conclusion
What Tailwind provides is a streamlined experience to web styling. It doesn’t require a massive amount of boilerplate to get started and certainly doesn’t push pre-styled button components or form elements which you might end up needing to restyle yourself.
Tailwind simply provides developers an efficient and fast method of styling so they can get straight to work. It can especially come in handy when you want to quickly add some pizzazz to early stage and personal projects, and it can even scale to larger projects as well.
