Use the Tailwind CSS Grid System

If you want to gain more understanding of how to use Tailwind's CSS Grid utilities, the good news is in this post I share knowledge on the subject with a variety of examples. I'll also be providing working code examples that you should feel free to use.

For anyone wondering, here's a visual representation of the layout:

Visual representation of the layout grid, including columns, header, main and footer areas
Visual representation of the layout grid, including columns, header, main and footer areas

It's your typical containerised layout solution, one that allows the container to span the full width of the page, yet constrains the content at a specified maximum width.

I'm a CSS Grid advocate

I'm a huge fan of CSS Grid, I always favour it for any kind of layout, I'm extremely biased towards it, I simply love the API and as I've been working with it for several years on both commercial & personal projects find it more familiar, the main reasons for this are:

  • CSS Grid is 2 dimensional, which means unlike flex items, grid items can be placed in 2 directions, horizontally and vertically (x & y).

  • With display: grid the amount of boilerplate HTML needed to create a complex layout is usually always less than it would be with display: flex.

  • The grid-gap property has been supported for longer, grid-gap was revolutionary, gaps were a huge problem in the world of CSS grid systems, you can see how obsessed over them I was by looking at this codepen collection of mine.

Enter Tailwind

Tailwind deconstructs a very popular 12 column grid system into series of utility classes that are categorised by the various properties of the CSS Grid spec, e.g.

/* grid-template-columns */
grid-cols-1: grid-template-columns: repeat(1, minmax(0, 1fr));
grid-cols-2: grid-template-columns: repeat(2, minmax(0, 1fr));
grid-cols-3: grid-template-columns: repeat(3, minmax(0, 1fr));
...
grid-cols-12: grid-template-columns: repeat(12, minmax(0, 1fr));

/* grid-column-start/end */
col-span-1: grid-column: span 1 / span 1;
col-span-2: grid-column: span 2 / span 2;
...
col-span-12: grid-column: span 12 / span 12;
Code examples from Tailwind's docs

I can't say I've ever written: grid-column: span 1 / span 1, it equates to grid-column: span 1 but this is Tailwind's internal code so we don't really need to worry about that when using it for simple layouts.

Tailwind 12 column grid

I'll cut to the chase, the following example is a series of constrained 12 column grids wrapped in containers that span the full width of the viewport, some content is omitted but you can always see the full version in the codepen.

<article class="grid gap-y-6">
  <div class="bg-red-100">
    <div class="max-w-7xl m-auto">
      <header class="grid grid-cols-12 gap-x-4">
        <img
          src="https://placekitten.com/150/150"
          alt="Kitteh industries Ltd."
        />
        <nav class="grid grid-flow-col col-span-11 justify-end gap-x-8 content-center">
          ...
        </nav>
      </header>
    </div>
  </div>
  <div class="bg-red-100">
    <div class="max-w-7xl m-auto">
      <main class="grid grid-cols-12 gap-x-4">
        <div class="col-span-4">
          <img src="https://placekitten.com/600/600" alt="Cute kitteh" />
        </div>
        <section class="col-span-8 grid gap-y-4 content-start">...</section>
      </main>
    </div>
  </div>
</article>
A constrained 12 column grid with content spanning different numbers of columns

Bear in mind that this is example is not yet responsive, that's next.

Responsive Tailwind 12 column grid

As I started to work though the upcoming responsive example using the previous one, I realised the markup structure wouldn't lend itself to the kind of layouts I want at different breakpoints. I then changed it, notice how the structure of the markup in the next example is different to the previous example, checkout the codepen.

<article class="grid gap-y-6">
  <div class="bg-red-100">
    <div class="max-w-7xl m-auto">
      <header class="grid grid-flow-col gap-x-4 px-6">
        <img
          width="64"
          height="64"
          src="https://placekitten.com/150/150"
          alt="Kitteh industries Ltd."
        />
        <nav class="grid grid-flow-col justify-end gap-x-8 content-center">
          ...
        </nav>
      </header>
    </div>
  </div>
  <div class="bg-red-100">
    <div class="max-w-7xl m-auto">
      <main class="grid grid-cols-12 gap-x-4 px-6">
        <section class="col-span-12 grid grid-cols-12 gap-x-4 gap-y-6 content-start">
          <img
            class="col-span-12 sm:col-span-4 row-span-3"
            src="https://placekitten.com/600/600"
            alt="Cute kitteh"
          />
          <h1 class="col-span-12 sm:col-span-8 font-bold text-7xl">
            Cute kitteh
          </h1>
          <div class="col-span-12 sm:col-span-8 grid gap-y-6">...</div>
        </section>
      </main>
    </div>
  </div>
</article>
A constrained, responsive 12 column grid with content spanning different columns at breakpoints

Responsive Tailwind 12 column grid with arbitrary values

Because of the use of margin: auto and the fact that it's <div/> city with the previous examples, I found myself writing this code the other day: grid-template-columns: 1fr minmax(0px, 1280px) 1fr;

<article class="grid gap-y-6">
  <div class="grid-cols-[1fr_minmax(0px,1280px)_1fr] bg-red-200 gap-x-6">
    <header class="grid grid-flow-col col-start-2">
      <img
        width="64"
        height="64"
        src="https://placekitten.com/150/150"
        alt="Kitteh industries Ltd."
      />
      <nav class="grid grid-flow-col justify-end gap-x-8 content-center">
        ...
      </nav>
    </header>
  </div>
  <main class="grid-cols-[1fr_minmax(0px,1280px)_1fr] bg-red-200 gap-x-6">
    <section class="grid grid-cols-12 col-start-2 gap-x-4 gap-y-6 content-start">
      <img
        class="col-span-12 sm:col-span-4 row-span-3"
        src="https://placekitten.com/600/600"
        alt="Cute kitteh"
      />
      <h1 class="col-span-12 sm:col-span-8 font-bold text-7xl">Cute kitteh</h1>
      <div class="col-span-12 sm:col-span-8 grid gap-y-6">...</div>
    </section>
  </main>
</article>
A constrained, responsive 12 column grid with content spanning different columns at breakpoints using arbitrary values

Doing it like this removes some of the excess HTML that you may or may not have to write when using Tailwind's layout system. I couldn't find a quick way to get the arbitrary classes to compile in either codepen or codesandbox so had to improvise, checkout the codepen.

I wasn't happy using what seems to me like an out of date practice, composing grid layouts using utility classes on more markup than is needed. I know, I know, I've just spent god-knows how long explaining how to to do that using Tailwind and provided examples, how contradictory of me 🤷‍♂️. I look at things from multiple perspectives, how you do this is down to what you're comfortable with.

When I'm in the throws of writing a lot of code using Tailwind I start to forget how to write CSS, or at-least how to think like I would if I was writing CSS. Otherwise I would normally come up with a 1 liner like that pretty quick.

You can get at me on Twitter, adios for now!