Tailwind emerged in 2017, survived the hype of new technologies and it is now present in many projects and in the standard installation of frameworks, such as NextJS. Tailwind makes styling much simpler, faster, and enjoyable.

distracted boyfriend meme

I've become a Tailwind evangelist, so I'd like to share its key features and how I use it in my daily work.

In this blog post, I'll be covering the following topics:

For more information on installation and configuration, please refer to the official Tailwind documentation.

How Tailwind CSS works

Tailwind utilizes HTML classes to apply CSS styles. For example, we can define the color, size and line-height of a text as follows with Tailwind.

<p class="text-red-500 text-base">Hello, World!</p>

In contrast, with pure CSS, we would have to create a class and use it in the element.

.text {
    color: red;
    font-size: 12px;
    line-height: 18px;
}
<p class="text">Hello, World!</p>

And with styled-components, we would need to export a component, import it, and use it. Typically, this element would be in a separate file.

export const Text = styled.p`
    color: red;
    font-size: 12px;
    line-height: 18px;
`;
import * as Styles from './styles.js';
// ...
<Styles.Text>Hello, World!</Styles.Text>

As you can see, we can achieve the same result by writing much less code with Tailwind.

Utility Classes

At first, it may take some time to memorize the classes, but they follow a pattern, and over time, it becomes natural. The official documentation provides a list of all classes, but the most commonly used ones are:

  • w-x - Width
  • h-x - Height
  • p-x - Padding
  • m-x - Margin
  • mb-x - Margin-bottom
  • mt-x - Margin-top
  • ml-x - Margin-left
  • mr-x - Margin-right
  • px-x - Padding-left & padding-right
  • my-x - Margin-top & margin-bottom
  • text-x - Font-size & color
  • leading-x - Line-height
  • bg-x - Background-color
  • rounded - Border-radius
  • flex | block | hidden | grid - display: flex | block | none | grid

Read more in the official documentation

I highly recommend using the VSCode Tailwind CSS IntelliSense extension, which suggests and shows the values of all classes as you type.

VSCode Tailwind CSS IntelliSense extension

Custom Theme

Tailwind comes with a default theme, but you can customize it to meet your project's needs.

To do this, simply create a tailwind.config.js file at the root of your project and define the properties you want to customize.

module.exports = {
  theme: {
    extend: {
      colors: {
        'blue': '#1fb6ff',
        'green': '#13ce66',
        'gray-dark': '#273444',
      },
      spacing: {
        '144': '36rem',
      },
      borderRadius: {
        '4xl': '2rem',
      }
    }
  }
}

Read more in the official documentation

Custom Properties

The Tailwind theme has a wide range of properties and styles that probably cover your design specifications.

However, if you happen to need a property that does not exist in your theme, you can define a different value using -[x], for example.

<p class="text-[red] text-[100px] w-[50%]">Hello, World!</p>

For properties with spaces, you can use an underscore _ to separate the values.

<p class="w-[calc(100%_+_10px)] shadow-[0_35px_60px_-15px_#333]">Hello, World!</p>

Read more in the official documentation

Using Media Queries

To use breakpoints, you can use the prefixes sm:, md:, lg:, and xl:.

<p class="text-red-500 sm:text-blue-500 md:text-green-500 lg:text-purple-500 xl:text-yellow-500">Hello, World!</p>

To change the sizes of the breakpoints, simply modify the screens property in the tailwind.config.js file.

module.exports = {
  theme: {
    screens: {
      'sm': '576px',
      // => @media (min-width: 576px) { ... }

      'md': '960px',
      // => @media (min-width: 960px) { ... }

      'lg': '1440px',
      // => @media (min-width: 1440px) { ... }
    },
  }
}

Read more in the official documentation

Hover, actived, disabled and other states

Tailwind also uses prefixes to style an element depending on its state, such as hover:, focus:, active:, and disabled:.

<button class="bg-blue-500 hover:bg-green-500 disabled:bg-slate-600">Click here</button>

Read more in the official documentation

Using !important

To use the !important property in CSS, simply add the ! prefix before the class.

<p class="!mb-0">Hello, World</p> <!-- margin-bottom: 0 !important; --->

Read more in the official documentation

Using Negative Values

To use negative values, simply use the - prefix before the class.

<p class="-mb-4">Hello, World</p> <!-- margin-bottom: -1rem; --->

Read more in the official documentation

Nested Elements

To style a child element, simply use the &> prefix inside brackets.

<div class="text-blue-700 hover:[&>.text]:text-red-700 ">
    <p>I'll not be red on hover.</p>
    <p class="text">I'll be red on hover.</p>
</div>

Read more in the official documentation

Targeting first and last element

Instead of using :not, :last-of-type, :first-of-type selectors to customize the first or last element of a group of sibling elements, simply use the first: and last: prefixes.

<p class="text-red-600 last:text-blue-600">...<p>
<p class="text-red-600 last:text-blue-600">...<p>
<p class="text-red-600 last:text-blue-600">...<p>

This is very useful in loops.

<ul>
    {#each people as person}
       <li class="mb-10 last:mb-0">...<li>
    {/each}
<ul>

Read more in the official documentation

Peer

To style an element depending on the state of its hierarchical sibling, use the peer class and prefix.

<input type="email" class="peer"/>
<p class="invisible peer-invalid:visible text-pink-600">
    Please provide a valid email address.
</p>

Read more in the official documentation

Improving readability with @apply

Some argue that a disadvantage of Tailwind is that it makes the code less readable by adding so many classes in the HTML.

<p class="text-base text-gray-800 mb-3 last:mb-0">Text 1</p>
<p class="text-base text-gray-800 mb-3 last:mb-0">Text 2</p>
<p class="text-base text-gray-800 mb-3 last:mb-0">Text 3</p>
<p class="text-base text-gray-800 mb-3 last:mb-0">Text 4</p>

While this may be valid, you can use @apply to group classes, reuse them, and make the code more legible.

.my-text-base {
    @apply text-base text-gray-800 mb-3 last:mb-0;
}
<p class="my-text-base">Text 1</p>
<p class="my-text-base">Text 2</p>
<p class="my-text-base">Text 3</p>
<p class="my-text-base">Text 4</p>

Read more in the official documentation

Using Prefix

If you want to add Tailwind to a project and avoid conflicts with other classes, you can add a tw- prefix to the Tailwind classes.

module.exports = {
  prefix: 'tw-',
}
<p class="tw-text-blue-400">Hello, World!</p>

Read more in the official documentation

Playground

Tailwind has a playground where you can test all these features and more online. Just visit the link.

https://play.tailwindcss.com/

Conclusion

Since I started working with Tailwind CSS, I rarely needed to create a new CSS file or rewrite properties to add style to a project.

In case I haven't convinced you to start using TailwindCSS yet, there are another points that I consider important to highlight.

  • TailwindCSS is light and only adds to the final bundle the classes that you used during the development.
  • TailwindCSS is easy to set up, customize and start working on any web project, weather using React, Angular, Vue or just HTML.
  • TailwindCSS can be used with other UI solutions, such as UI libraries, preprocessors and CSS-in-JS.

I hope you enjoyed this my blog post. If you have any questions, feel free to ask in the comments section below.