Advanced Grid

The Grid System Basics lesson covered the standard pattern — a .row with a .col-md-4 (or similar) on every single child. That works, but it means editing every card's class whenever TrailMap's column count changes. Bootstrap 5's grid has a few more tools for exactly this kind of situation: auto-sizing all columns in a row at once, reordering columns visually without touching the HTML, pushing a column over with empty space, and nesting an entire grid inside a single column.

.row-cols-* — Auto-Sizing Every Column at Once

Instead of adding .col-md-4 to each of TrailMap's trail cards individually, .row-cols-md-3 on the parent .row tells Bootstrap "fit 3 equal columns per row" — every direct .col child sizes itself automatically:

<div class="row row-cols-1 row-cols-md-3 g-4">
  <div class="col">...</div>
  <div class="col">...</div>
  <div class="col">...</div>
</div>

.row-cols-1 stacks single-column on small screens, .row-cols-md-3 switches to 3 per row at the md breakpoint up. Add a fourth or tenth trail card later and no class needs to change on any of them — the row keeps reflowing at 3 per row.

.order-* — Reordering Columns Visually

Sometimes source order (good for screen readers and keyboard tab order) and visual order need to differ. .order-* changes only how a column is displayed, not where it sits in the HTML:

<div class="row">
  <div class="col-md-4 order-md-2">Trail photo</div>
  <div class="col-md-8 order-md-1">Trail description</div>
</div>

Here the description column comes second in the markup but renders first, on medium screens and up, because of order-md-1 versus order-md-2. On small screens (no order class applies) they simply render in source order.

.offset-* — Pushing a Column Over

.offset-md-* adds empty grid space before a column, useful for centering a narrower block like a single featured TrailMap trail without wrapping it in an extra row:

<div class="row">
  <div class="col-md-6 offset-md-3">
    <!-- 6 columns wide, pushed over by 3 empty columns — centers it in a 12-col row -->
    Featured Trail: Eagle Ridge
  </div>
</div>

Nested Grids — A Row Inside a Column

Any .col can contain its own .row, creating an independent 12-column grid scoped to that column. TrailMap uses this for a trail card whose body needs its own two-column stat layout inside a page-level three-column card grid:

<div class="row">
  <div class="col-md-6">

    <!-- nested grid, scoped only to this column -->
    <div class="row">
      <div class="col-6">Distance: 5.2 mi</div>
      <div class="col-6">Elevation: 1,100 ft</div>
    </div>

  </div>
</div>
Note: the nested .row is still relative to its own 12-column width, not the page's — .col-6 inside it means "half of this column," not "half the page."

Worked Example: TrailMap's Card Grid with row-cols-md-3

Putting the auto-sizing technique into a full trail-card grid removes the need to ever touch an individual card's column class again:

<div class="row row-cols-1 row-cols-sm-2 row-cols-md-3 g-4">
  <div class="col">
    <div class="card h-100">
      <img src="eagle-ridge.jpg" class="card-img-top" alt="Eagle Ridge Trail">
      <div class="card-body">
        <h5 class="card-title">Eagle Ridge Trail</h5>
      </div>
    </div>
  </div>
  <!-- more .col cards, no per-card sizing class needed -->
</div>

One column per row on phones, two on tablets, three from md up — set once, on the parent, and every card just falls into place.

Next: Layout is only half the story. Accessibility covers what Bootstrap already handles for you and what's still on you.