Fluid grid columns with tailwind

I saw a recent tweet that looked at a way to do responsive grid with TailwindCSS without using breakpoints. It struck me as an interesting way to handle the situation so I thought I’d break it down to better understand what is going on.

Original Code

<div 
  class="grid grid-cols-[repeat(auto-fill,minmax(theme(width.64),1fr))] p-2 gap-2"
>
  <div class="bg-blue-500 aspect-video"></div>
  <div class="bg-blue-500 aspect-video"></div>
  <div class="bg-blue-500 aspect-video"></div>
  <div class="bg-blue-500 aspect-video"></div>
</div>

The interesting bit is the grid-cols. This is using the arbitrary values feature of Tailwind so what is inside is mostly straight CSS.

We can re-flow the code to see how everything is nested:

repeat(
  auto-fill,
  min-max( theme(width.64), 1fr )
)

repeat() is a CSS function that essentially takes two arguments, the first says how many times to repeat a value and the second is the value to repeat.

Let’s defer auto-fill for a bit while we look at min-max (the Tailwind-friendly version of minmax()). minmax() is a CSS grid function that defines boundaries for a size. The returned value will never be less than 16rem (based on default theme width value of 64 using the theme() Tailwind function) and never greater than 1fr.

The auto-fill value mean “the number of repetitions is the largest possible positive integer that does not cause the grid to overflow its grid container”. So, if the grid is less than 536px there will be one column (since the “minimum” cell width is 256px – twice that plus the 8px padding on each side and 8px gap between columns adds to 536px).

If the grid width is 536px <= W < 800px then there will be 2 columns.

If the grid width is 800px <= W < 1064px then there will be 3 columns.

This approach means that cells will never be smaller than 256px wide and every time the container is wide enough to support another column while maintaining the minimum cell width then another column will be automatically added.

More Traditional Approach

Let’s contrast this with a more traditional approach that uses breakpoints to define grid columns.

<div class="grid gap-2 p-2 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 xl:grid-cols-5">
  <div class="bg-red-500 aspect-video"></div>
  <div class="bg-red-500 aspect-video"></div>
  <div class="bg-red-500 aspect-video"></div>
  <div class="bg-red-500 aspect-video"></div>
</div>

I setup an example in the Tailwind Playground to explore the example and demonstrate how the two solutions are similar/different.

Source: The original source for this idea was a tweet from @heyImMapleLeaf