TailwindCSS is a utility-first CSS framework for rapid UI development.

CSS problematics

CSS is a language created in 1996. And since 1996, developers are struggling about design and how to structure their CSS. Spoiler : at the end, it is often ugly and unmaintainable !

To avoid problems, some technics and CSS frameworks have born to give class naming conventions. The most popular are Bootstrap, Fundation or Bulma, which are a high level component philosophy. Out of the box, it provides generic classes which we can use.

Those frameworks provide components like buttons, dropdowns, cards, forms … For example, if we need styled components, we can write:

<div class="card">
<img class="card-img-top" src="..." alt="Card image cap" />
<div class="card-body">
<h5 class="card-title">Card title</h5>
<p class="card-text">
Some quick example text to build on the card title and make up the bulk of
the card's content.
<a href="#" class="btn btn-primary">Go somewhere</a>
<button type="button" class="btn btn-primary">Primary</button>
<button type="button" class="btn btn-secondary">Secondary</button>
<button type="button" class="btn btn-success">Success</button>

Here, we don’t focus about the style of the components, but we focus about the role of a component.

High level component approach is great. We only have to define a role for each component, and the framework built a UI for us. But a big disadvantage is that it is very hard to customize.

Philosophy of TailwindCSS

There are only two hard things in Computer Science: cache invalidation and naming things — Phil Karlton

Utility first

TailwindCSS is a very different CSS Framework. Instead of offering high level components to use, Tailwind offers a more functional approach.

To display a card, we will write this instead:

class="mx-auto flex max-w-sm items-center space-x-4 rounded-xl bg-white p-6 shadow-lg"
<div class="shrink-0">
<img class="h-12 w-12" src="/img/logo.svg" alt="Logo" />
<div class="text-xl font-medium text-black">Chat</div>
<p class="text-slate-500">You have a new message!</p>

The approach here is to use a lot of utility classes.

  • flex means display: flex
  • bg-white means background-color: white
  • mx-auto means margin-left: auto; margin-right: auto
  • etc…

The approach is very different ! Instead of defining roles, we define styles.

Tailwind offers thousands and thousands of classes we can use.

And why is it more maintainable ? Isn’t it better to separate HTML and CSS ? Actually, Tailwind community says that this organization gives a much more maintainable CSS structure. 🤷🏼‍♂️

Huge teams create a bunch of css class names that override other developers CSS classes etc… then some get deprecated so now you have CSS classes in your CSS file that don’t exist anymore etc…

Utility classes aren’t the same as inline styles

Do you think these two lines are equivalent ?

<article style="background-color: red"></article>
<article class="bg-red-500"></article>

But why ? We already have the style attribute we can apply on HTML tags.

Let’s dig out that !


First, Tailwind offers a lot of constants that we can use.

For example, tailwind offers :

Responsive design

Tailwind offers default breakpoints we can use. We can conditionally apply styles if we are on a mobile, tablet, computer, TV, printer… The syntax is very nice.

<img class="w-16 md:w-32 lg:w-48" src="..." />

Here, the image will have a width:

  • Size 16 by default on small devices
  • Size 32 on medium size screens (@media (min-width: 768px))
  • Size 48 on large size screens (@media (min-width: 1024px))

Hover, focus, states…

With tailwind, we can define Pseudo-classes, Pseudo-elements, Attribute selectors, and so much more…


These states aren’t available on inline styles

<button class="bg-sky-600 hover:bg-sky-700">Save changes</button>
<button class="bg-orange-600 focus:bg-orange-700">Save changes</button>
<div class="ltr:ml-3 rtl:mr-3">...</div>

We can even add an !important property by adding a ! before the class name !

<div class="!bg-amber-400">...</div>
<!-- background-color: ... !important; -->

Dark mode

Tailwind offers a dark mode strategy :

<div class="bg-slate-200 dark:bg-slate-800">My dark theme !</div>

Here, the background color will change if the user requests a dark theme or not.


And of course we can combine as we want the selectors : 😊

<button class="dark:md:hover:bg-fuchsia-600">Save changes</button>

Classes generations

And even you need more, you can generate specific classes with [] syntax like this:

<button class="bg-[#1da1f2] text-white">
<svg><!-- ... --></svg>
Share on Twitter
<div class="after:bottom-[-5px]"></div>

A lot of customization

Finally, if you aren’t satisfied, or if you want specific constant values for a specific design system, you can create a tailwind.config.js config file, and configure as you want. Here is an example:

const defaultTheme = require("tailwindcss/defaultTheme");
/** @type {import('tailwindcss').Config} */
module.exports = {
content: ["./src/**/*.{html,js}"],
theme: {
colors: {
blue: "#1fb6ff",
purple: "#7e5bef",
pink: "#ff49db",
fontFamily: {
sans: ["Graphik", "sans-serif"],
serif: ["Merriweather", "serif"],
extend: {
fontFamily: {
sans: ["Inter var", ...defaultTheme.fontFamily.sans],
spacing: {
"8xl": "96rem",
"9xl": "128rem",
borderRadius: {
"4xl": "2rem",
variants: {},
plugins: [

How TailwindCSS works

JIT (Just in time) mode

With all these classes, you might ask :

OK, but the CSS file must be HUGE with all these CSS classes ?!

With the tailwind.config.js config file, you can specify where the HTML code is, and Tailwind will automatically parse and generate a (small) CSS file with only the used classes.

module.exports = {
content: ["./pages/**/*.{html}", "./components/**/*.{jsx,vue}"],


CSS Plugins

TailwindCSS offers some other plugins to customize forms, aspect ratio or line clamp.

A very interesting one is the typography plugin.

[…It] provides a set of prose classes you can use to add beautiful typographic defaults to any vanilla HTML you don’t control, like HTML rendered from Markdown, or pulled from a CMS. https://tailwindcss.com/docs/typography-plugin

<section class="prose">
<h1>My stylized title</h1>
<p>My stylized paragraph</p>
<p>My second stylized paragraph</p>

So we don’t need to add classes on every element to style everything !

Other plugins

TailwindCSS offers a VSCode plugin, to automatically autocomplete classes. It can be found there : https://marketplace.visualstudio.com/items?itemName=bradlc.vscode-tailwindcss.

There is a prettier plugin, which does a sorting of class name. It can be found there : https://tailwindcss.com/blog/automatic-class-sorting-with-prettier.

Design patterns

When we will use Tailwind, of course, duplication will happen :

<nav class="flex justify-center space-x-4">
class="rounded-lg px-3 py-2 font-medium text-slate-700 hover:bg-slate-100 hover:text-slate-900"
class="rounded-lg px-3 py-2 font-medium text-slate-700 hover:bg-slate-100 hover:text-slate-900"
class="rounded-lg px-3 py-2 font-medium text-slate-700 hover:bg-slate-100 hover:text-slate-900"
class="rounded-lg px-3 py-2 font-medium text-slate-700 hover:bg-slate-100 hover:text-slate-900"

But how to manage with that ?


If you still love codding in CSS, you can create your CSS components like this:

@tailwind base;
@tailwind components;
@tailwind utilities;
@layer base {
.link {
@apply rounded-lg px-3 py-2 font-medium text-slate-700 hover:bg-slate-100 hover:text-slate-900;

This approach works, but it is not the recommended approach.

Component approach

The component approach is to export our code to external partials.

function MyLink({ link, children }) {
return (
class="rounded-lg px-3 py-2 font-medium text-slate-700 hover:bg-slate-100 hover:text-slate-900"
function Index() {
return (
<nav class="flex justify-center space-x-4">
<MyLink link="/dashboard">Home</MyLink>
<MyLink link="/team">Teal</MyLink>
<MyLink link="/projects">Projects</MyLink>
<MyLink link="/reports">Reports</MyLink>

Then, we can reuse the components ! No duplications anymore !



  • TailwindCSS offers a lot of personalization with its functional approach. It offers a lot of constants and shortcut that we can use to compose our page. Development is faster ! 🚀

  • No need to name things anymore !

  • Tailwind removes the fear of breaking stuff when we are doing a design update. CSS is more maintainable !

  • As Tailwind is close from CSS, upgrades are very easy to make ! 🔥 If you are using bootstrap, migrating from Bootstrap 4 to Bootstrap 5 is a hell ! 🌋

  • CSS won’t become wider and wider as the project grows 😊 If you don’t use classes, Tailwind won’t generate them. No CSS dead code anymore !

  • The ecosystem of Tailwind is very nice. Development is comfortable with the VSCode plugins. It is very easy to include it in a ReactJS or VueJS project too !

  • The documentation of TailwindCSS is great and has a lot of examples !


  • Tailwind needs a lot of tools to work (Tailwind CLI, setup config, install the VSCode extension…)

  • Styling and HTML are mixed. The HTML can become ugly.

  • Learning Tailwind takes time. OK, Tailwind is intuitive, but the first days may be hard because you have to always look at the documentation.

  • Tailwind isn’t a standard. Classnames may change over the time.

  • Tailwind doesn’t come with any pre-styled components. So if you don’t know how your website will look, starting may be harder.

    • Note: You can find some pre-designed components on the internet. The official dev team of Tailwind sells a pack of nice looking components : https://tailwindui.com/components

My opinion

For large projects, Tailwind is the perfect choice for me !

If you already know CSS, Tailwind is worth to learn. It changes the way you develop. But if you aren’t familiar, first spend time to learn CSS instead. Yes, HTML is ugly, but please at least try it 😊 !

TailwindCSS powers my blog, and I am very happy with it ! I could design very quickly with all the constants and helpers. A lot of configuration is already made.

All the styles are in the same place : so no separate media queries in CSS files !

I loved the developer experience and how Tailwind integrates well with Prettier or VSCode !

Go to further

Recommended articles