Chapter 9 of 14 · Tailwind CSS for Beginners — Complete Free Tutorial

Grid with Tailwind

When an interface needs rows and columns at the same time — galleries, dashboards, pricing tables — CSS Grid is the tool, and Tailwind's grid utilities are thin, honest wrappers around it. This chapter of the Tailwind CSS for Beginners series covers column and row control, spanning, alignment and gap, then builds a responsive gallery and a dashboard shell. The theory lives in CSS Grid Essentials; here you learn the class names.

Declaring columns

The shortest version of Grid is one class plus a column count:

<div class="grid grid-cols-3 gap-4">
  <div class="bg-slate-100 p-4">One</div>
  <div class="bg-slate-100 p-4">Two</div>
  <div class="bg-slate-100 p-4">Three</div>
  <div class="bg-slate-100 p-4">Four</div>
  <div class="bg-slate-100 p-4">Five</div>
  <div class="bg-slate-100 p-4">Six</div>
</div>

Expected output:

Three equal columns of pale grey boxes with even gaps. The fourth box
wraps onto a second row automatically, and the last row ends flush
with the first.

The available counts run grid-cols-1 through grid-cols-12, and beyond them arbitrary values take over: grid-cols-[repeat(auto-fit,minmax(240px,1fr))] is legal when you want the browser to decide the column count. Rows work the same way with grid-rows-2, though most layouts let rows create themselves. The generated CSS behind grid-cols-3 is one line — grid-template-columns: repeat(3, minmax(0, 1fr)) — and that minmax(0, 1fr) is deliberate: it stops long words from forcing a track wider than its share, a trick worth remembering when text starts overflowing.

Column and row control

UtilityPropertyUse
col-span-2grid-column: span 2A wide feature card among narrow ones
col-start-3grid-column-startPin an item to a specific track
col-span-fullgrid-column: 1 / -1Stretch across every column
row-span-2grid-row: span 2A tall tile occupying two rows
grid-flow-row-densegrid-auto-flowBackfill gaps left by spanning items
auto-rows-[120px]grid-auto-rowsFixed implicit row heights

Spans are how dashboards are assembled: a sidebar with row-span-2, a stat card with col-span-2, and a full-width chart using col-span-full. Everything still collapses to a single column on phones, because you will change nothing but grid-cols- at each breakpoint.

Gap and alignment

Grid has its own spacing model: gap-x-4 and gap-y-8 set the gutters between tracks, and they never collapse or double up. Alignment is handled by three groups of utilities:

  • Per cell — justify-self-center and self-end position one item inside its own area.
  • Per column — justify-items-center and items-stretch set the default for every cell in the container.
  • Whole grid — place-content-center moves the grid itself when it is smaller than its container.

The everyday combination is items-start on the container for top-aligned cards, or leaving the default stretch so cards in one row share a height. Since gutters are controlled by one property, restyling a whole grid often means changing a single class — the spacing cannot drift between rows the way it can when every child carries its own margins.

A responsive gallery

Combining columns with breakpoints produces a gallery with no media query of your own to maintain:

<section class="grid grid-cols-1 gap-6 sm:grid-cols-2 lg:grid-cols-4">
  <figure class="overflow-hidden rounded-lg border border-slate-200 bg-white">
    <div class="aspect-square bg-slate-200"></div>
    <figcaption class="p-3 text-sm text-slate-700">Placeholder image</figcaption>
  </figure>
  <!-- repeat for the other tiles -->
</section>

Expected output:

One column of square-topped tiles on a phone, two columns on a
tablet, four on a laptop. Gaps stay identical at every width and no
tile is ever clipped.

Notice that only the column class changes per breakpoint — the gap, the borders and the aspect ratio never need touching. Chapter 10 explains the sm: and lg: prefixes in depth.

Choosing between grid and flexbox

Both can produce identical-looking layouts, so the honest rule is about intent:

  1. One row of items with alignment — navigation bars, button groups and icon rows are flex, always.
  2. Rows and columns that must line up — galleries, card grids and dashboard panels are grid.
  3. Content-driven stacking — a column of paragraphs with gap-4 is flex-col, or simply block layout.
  4. Two dimensions plus spanning — if something must cross rows or columns, only grid can do it.

A practical hybrid: make the page shell a grid, then use flex inside each cell for the local arrangement. That is how nearly every real application is structured.

Common mistakes

  • Grid for a single row — grid-cols-3 on a toolbar produces columns you do not want; flex is simpler there.
  • Ignoring implicit rows — spanning items can silently create extra rows unless you size them with auto-rows-.
  • Hard-coding many columns — four breakpoints each with a different grid-cols- is fine; eight is a maintenance problem, and auto-fit with minmax() may be better.
  • Forgetting gap — margins on grid children are unnecessary and fight the track gutters.
  • Assuming items size themselves — a long word can expand a track, so text-heavy cells often need min-w-0.

Practice checklist

  1. Build a 3-column gallery and add sm: and lg: column variants.
  2. Give the first tile col-span-2 and confirm the others reflow around it.
  3. Assemble a dashboard shell: sidebar, two stat cards and a full-width chart.
  4. Set items-start on a grid of uneven cards, then remove it and compare heights.
  5. Try grid-flow-row-dense with a spanning item and watch gaps backfill.

Grid is where responsiveness starts to matter — Responsive Design with Breakpoints is next.

Quiz: Grid with Tailwind

5 questions · 70% to pass

Frequently Asked Questions

Tailwind is a utility-first CSS framework: instead of writing custom classes like .card-title, you compose elements from small single-purpose utilities such as text-lg font-semibold text-slate-800. The styles ship as a generated stylesheet containing only the classes your project uses, so the CSS stays small and consistent.

Bootstrap ships a opinionated component layer (buttons, navbars with Bootstrap's own look) that you override with custom CSS. Tailwind ships primitive utilities and lets you design freely — two sites built with Tailwind can look completely different, while two Bootstrap sites tend to look related. You can still build components; you just compose them from utilities first.

You need the fundamentals: the box model, specificity, Flexbox, Grid, media queries and pseudo-classes. Tailwind does not replace CSS knowledge — it renames it. Understanding what padding, margin, gap and z-index mean makes every utility class obvious instead of something to memorise.

v4 is CSS-first: configuration lives in CSS with @import "tailwindcss" and @theme tokens instead of a JavaScript tailwind.config.js, the engine is rewritten in Rust for much faster builds, and modern CSS features (container queries, cascade layers) are built in. This tutorial teaches v4 and notes where v3 differed.

Long class lists are a real trade-off, and the tutorial covers two fixes: consistent ordering (layout → spacing → typography → colour) and small component classes for repeated combinations. The generated CSS contains only classes you actually use — Tailwind removes everything else at build time, so the stylesheet is typically smaller than an unused framework.

Three utilities cover most cases: mx-auto centres a fixed-width block horizontally, flex items-center justify-centre centres children inside a flex parent, and grid place-items-center does the same for grids. Chapter 8 and chapter 9 show both patterns with examples.

Yes — Tailwind is a build step that scans your template files for class names and generates CSS, so it works with any framework or none. It does not ship runtime JavaScript, and the classes look the same in JSX, Blade, PHP or static HTML files.

In v4 you define design tokens in CSS with @theme, for example --color-brand-500: #4f46e5; creates bg-brand-500, text-brand-500 and friends. For a one-off value you can always use arbitrary values like bg-[#0f172a], which need no configuration at all.

A variant prefixes a utility with the condition it applies under: hover:bg-indigo-600 on hover, focus:ring-2 while focused, dark:bg-slate-900 in dark mode, and sm: / md: / lg: at breakpoints. Variants stack, such as md:hover:text-lg, and chapter 11 covers the full pattern.

Yes. Tailwind compiles to a static stylesheet with no JavaScript requirement, and because it ships only used classes, pages stay fast — a Core Web Vitals win that helps SEO. Accessibility, semantic markup and good content remain your job; Tailwind only styles what you write.