The Tailwind CSS framework follows a CSS principle called DRY(Don’t Repeat Yourself). We don’t reuse over and over again the same CSS properties and values, but we do reuse the reference to them via HTML classes. This means that the CSS bundle will get really small, but HTML files will get bigger. So I guess the “Nothing is lost … everything is transformed” aphorism is true after all.

All that repeated CSS rule turns into repeated classes and that will flood the HTML document with “spaghetti classes”. Well that is not actually accurate, that when you get one end of the spaghetti class the rest will fall with it. That is because the classes are single-role classes and they work independently, without any context.

Anyway, in this article we will dive deep into the syntax of Tailwind and see how we do things around here.

Abbreviation rules

Tailwind doesn’t abbreviate every CSS property since, there needs to be a certain balance between readability/easy-understanding of that class name and shortening code for the sake of writing less code. For example border is written out, but top is just a t. Why? Well, since you already wrote border- the t intuitively is matched with top in our minds. Of course there are exceptions from this rule, like w- stands for width. Let’s see some abbreviations:

t - top
b - bottom
r - right
l - left
tl - top left
tr - top right
bl - bottom left
br - bottom right
bg - background
p - padding
pr - padding right
.....padding with the rest of directions
m - margin
mb - margin bottom
... margin with the rest of directions
flex - flexbox

Representation of numeric values

There are many keywords or number representations for the actual length + unit, but they differ from property to property. Let’s check out a few of them:

xs -   0.75rem/1
sm -   0.875rem/1.25
base - 1rem/1.5
lg -   1.125rem/1.75
xl -   1.25rem/1.75
2xl -  1.5rem/2
3xl -  1.875rem/2.25
4xl -  2.25rem/2.5
5xl -  3rem/1
6xl -  3.75rem/1
7xl -  4.5rem/1
8xl -  6rem/1
9xl -  8/1

3 -  .75rem
4 -  1rem
5 -  1.25rem
6 -  1.5rem
7 -  1.75rem
8 -  2rem
9 -  2.25rem
10 - 2.5rem
none - 1rem
tight - 1.25rem
snug - 1.375rem
normal - 1.5rem
relaxed - 1.625rem
loose - 2rem

Letter spacing
tighter - -0.05em
tight - -0.025em
normal - 0
wide - 0.025em
wider - 0.05em
widest - 0.1em

Width and height
px - 1px
0.5 - 0.125rem
1 - 0.25rem
1.5 - 0.375rem
2 - 0.5rem
2.5 - 0.625rem
3 - 0.75rem
3.5 - 0.875rem
4 - 1rem
5 - 1.25rem
6 - 1.5rem
7 - 1.75rem
8 - 2rem
9 - 2.25rem
10 - 2.5rem
11 - 2.75rem
12 - 3rem 
14 - 3.5rem
16 - 4rem
20 - 5rem
24 - 6rem
28 - 7rem
32 - 8rem
36 - 9rem
40 - 10rem
44 - 11rem
48 - 12rem
52 - 13rem
56 - 14rem
60 - 15rem
64 - 16rem
72 - 18rem
80 - 20rem
96 - 24rem
full - 100%
screen - 100vw or 100vh 

As you can see the learning curve would be steep if you would start to mug up all these mappings. But you can always revisit their website and look for a value, which is of course time consuming.

Combined values

.text-red-600 - { color: rgba(255,0,0,.6) }   // red color that has .6 opacity
.gap-x-3 - { column-gap: .75rem }  //horizontal gap between columns of a grid
.px-4 -  { 
    padding-left: 1rem;
    padding-right: 1rem;

Missing or partially missing property names

.block - { display: block }
.shadow-xl - { 
    --tw-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
    box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);  

Renamed property names

.rounded-tl-lg - { border-top-left-radius: 0.5rem; }
.ring-2 -  { 
   box-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color); 
.divide-x-4 {
   border-right-width: 0px;
   border-left-width: 4px;

Hover, focus, active states

<div class="hover:bg-red-300 focus:outline-none focus:text-white-900 active:bg-green-500"></div>

Any existing Tailwind class prefixed with the state and separated with a colon represents CSS added on those states. If you need to add 10 CSS rules on hover that html tag will get crowded in a second.

Group hover

When it comes to hidden elements the hover does not work, but group hover does !

<div class="group">
   <span class="group-hover:opacity-100">

Media queries

You can write media queries the same way you wrote the hover states.

<div class="sm:py-2 md:py-4 lg:py-6"></div>

Enough of the “cheatsheet”, let’s see some magic !

JIT(Just in time) compilation(run-time compilation) was introduced in Tailwind at version 2.1 and the novelty in writing CSS classes was upgraded to a new level, where values are added at run-time instead of build time. The build time decreased a lot with JIT. Variants like active, disabled, and others are not normally enabled by default because of avoiding large file sizes, but all of them are enabled in JIT mode. Styles in this mode are generated on demand, this way css files contain only the needed/used styles, so no need to purge them as the definition of perfection says – when there is nothing to take away to make it better.

<div class="w-[130px] pr-[15px] bg-[#fcc]"></div>

Note: Scanning your HTML files and comparing the used classes to the defined classes, a new CSS file will be created based on that comparison with only the needed classes but it’s crucial that you configure the purge option in your tailwind.config.js file with all of your HTML template paths, otherwise your CSS files will be empty.

// tailwind.config.js
  module.exports = {
    mode: 'jit',

    purge: [
     './src/**/*.{jsx, tsx}',

Let’s see what are the variants that JIT enabled:

  • before, after pseudo elements
  • first-letter, first-line
  • selection
  • empty
  • first-of-type, last-of-type, only-of-type
  • target
  • default, indeterminate, placeholder-shown, autofill, valid, invalid, required, in-range, out-of-range
<div class="empty:hidden before:content-['Welcome!'] before:flex
<input class="invalid:text-red-800 valid:text-green-900" />

Variants are even stackable

<input class="md:invalid:hover:focus:bg-red-800" />

Selections and carets

<body class="selection:bg-green-800 selection:text-white-300">
<input class="caret-green-500" />

The infamous !important

<div class="!text-red-400 !opacity-50"></div>


In the example below when the input becomes invalid the associated paragraph tag will get a visible class and it will become visible.

<input type="email" class="peer" required />
<p class="peer-invalid:visible">This field is required</p>

How about theming in Tailwind

Since those fancy text and background color classes are pretty color specific, when your boss/client decides to change the branding color of the website, you will have a lot of places where you need to take out classes like .text-yellow-500. The fact is I wouldn’t use the native text and background color classes and would create a list of colors that will represent the brand of the company.

You have to add some changes in the tailwind.config.js

theme: {
   extend: {
      textColor: {
          primary: 'var(--color-text-primary)',
          secondary: 'var(--color-text-secondary)',
          disabled: 'var(--color-text-gray)',
          links: 'var(--color-text-links)'  
      backgroundColor: {
           primary: 'var(--color-bg-primary)',
           secondary: 'var(--color-bg-secondary)'  
      gradientColorStops: {  
          fill: 'var(--color-fill)'

Writing extra CSS

You can also write extra CSS in a .css file, but there is a methodology to do that, certain steps would be nice to be followed. First you import the libraries that you want to be added and then you wrap your css code in a @layer directive, that will extend one of those libraries and the @apply directive that will group together multiple classes

@tailwind base;
@tailwind components;
@tailwind utilities;

@layer components {
  .list-item {
     @apply pb-4 text-black-500 md:mb-4 sm:mb-1 hover:text-orange-600

Now the @apply directive has the power to give an abstraction to multiple classes grouped together but this is anti-pattern for what Tailwind proposed to do as a purpose. Use it cautiously and rarely. If you want to use classes that have multiple css rules inside of it then you should use Bootstrap or Bulma, Tailwind stands for single-purpose utility classes not for component classes.

You can also add CSS variables in the @layer directive.

@layer base {
   :root {
      --color-red: #f00;
      --color-secret: #cf0;

That’s it for today, for detailed syntax discussion please read the part 3 of these series.

How useful was this post?

Click on a star to rate it!

Average rating 5 / 5. Vote count: 1

No votes so far! Be the first to rate this post.

Categorized in: