Cards
The card is Bootstrap 4's flexible content container — it replaced Bootstrap 3's three separate panel, thumbnail, and well components with one unified box. TrailMap's whole trail-listing page is built out of cards, so this lesson goes deeper than most: every card part, header/footer, and the two multi-card layout helpers.
1. Anatomy of a Card
A card is a .card wrapper, almost always holding a .card-body for padded
content. Inside the body, .card-title styles a heading-like element and
.card-text styles a paragraph with the correct bottom margin.
<div class="card" style="width: 18rem;">
<div class="card-body">
<h5 class="card-title">Card title</h5>
<h6 class="card-subtitle mb-2 text-muted">Card subtitle</h6>
<p class="card-text">Some quick example text to build on the card title.</p>
<a href="#" class="card-link">Card link</a>
</div>
</div>
2. Images: .card-img-top
An image placed directly inside .card (as a sibling before .card-body,
not nested inside it) with .card-img-top stretches full-width and gets rounded top
corners that match the card.
<div class="card" style="width: 18rem;">
<img src="trail-photo.jpg" class="card-img-top" alt="Trail photo">
<div class="card-body">
<h5 class="card-title">Ridgeline Loop</h5>
<p class="card-text">A steady climb with sweeping valley views near the summit.</p>
</div>
</div>
3. Header and Footer: .card-header / .card-footer
.card-header and .card-footer add a visually separated strip above or
below .card-body, useful for a title bar or a timestamp/metadata line.
<div class="card">
<div class="card-header">Featured Trail</div>
<div class="card-body">
<h5 class="card-title">Sunset Ridge Trail</h5>
<p class="card-text">Best hiked in the last two hours before dusk.</p>
</div>
<div class="card-footer text-muted">Updated 3 days ago</div>
</div>
4. Multiple Cards: .card-group and .card-deck
.card-group attaches a row of cards edge to edge with shared borders, like a single
connected strip. .card-deck instead lays cards out as separate boxes of equal height
with consistent gutters between them — closer to a grid of independent cards.
<!-- card-group: edge-to-edge, shared borders -->
<div class="card-group">
<div class="card">
<div class="card-body">
<h5 class="card-title">Sunset Ridge</h5>
<p class="card-text">3.2 mi · Easy</p>
</div>
</div>
<div class="card">
<div class="card-body">
<h5 class="card-title">Ridgeline Loop</h5>
<p class="card-text">4.8 mi · Hard</p>
</div>
</div>
</div>
<!-- card-deck: equal height, spaced apart -->
<div class="card-deck">
<div class="card">
<div class="card-body">
<h5 class="card-title">Sunset Ridge</h5>
<p class="card-text">A short intro line that is a bit longer here.</p>
</div>
</div>
<div class="card">
<div class="card-body">
<h5 class="card-title">Ridgeline Loop</h5>
<p class="card-text">Short intro line.</p>
</div>
</div>
</div>
.card-deck entirely — its equal-height, evenly-gapped layout is now built with the
regular grid plus the gap utility instead (e.g. row row-cols-3 g-4). If
you're maintaining a Bootstrap 4 codebase, .card-deck is still the correct, supported
way to do this; there is no equivalent single class to reach for if you ever port the markup forward.5. Worked Example: The TrailMap Trail Card
This is the actual card TrailMap repeats across its trail-listing page: a top photo, a title with an inline difficulty badge, a truncated one-line description, a footer with distance and rating, and a full-width action button.
<div class="card" style="width: 20rem;">
<img src="ridgeline-loop.jpg" class="card-img-top" alt="Ridgeline Loop trail">
<div class="card-body">
<h5 class="card-title text-truncate">
Ridgeline Loop
<span class="badge badge-danger">Hard</span>
</h5>
<p class="card-text text-truncate">
A steady climb with sweeping valley views near the summit.
</p>
<a href="#" class="btn btn-primary btn-block">View Trail</a>
</div>
<div class="card-footer text-muted">
4.8 mi · ★ 4.6 (112 reviews)
</div>
</div>