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>
.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.