Skip to content

Styling the Tours Page — Tour Cards, Grid Layout, and Hover Effects

The tours page is the functional heart of the STO site — a scannable product listing where visitors discover which hikes are available. This lesson builds it with a more detailed card layout than the homepage preview, polished hover effects, and category tags.

A consistent page header treatment used on every interior page:

/* === Page Header === */
.page-header {
background-color: var(--color-primary);
padding: var(--space-xl) 0;
text-align: center;
}
.page-header h1 {
color: var(--color-bg);
font-size: 2.5rem;
margin-bottom: var(--space-sm);
}
.page-header p {
color: var(--color-accent);
font-size: 1.125rem;
max-width: 560px;
margin: 0 auto;
}

This same .page-header block is reused on tours, blog, about, and contact pages — one rule, consistent across all interior pages.

Tags let users visually scan for the type of tour they want:

/* === Tour Tags === */
.tour-tags {
display: flex;
flex-wrap: wrap;
gap: var(--space-sm);
margin-bottom: var(--space-lg);
}
.tour-tag {
display: inline-block;
background-color: var(--color-accent);
color: var(--color-primary);
font-size: 0.75rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.05em;
padding: 0.25rem 0.75rem;
border-radius: var(--radius-full);
}
.tour-tag-difficulty-hard {
background-color: var(--color-primary);
color: var(--color-white);
}
.tour-tag-difficulty-moderate {
background-color: var(--color-secondary);
color: var(--color-white);
}
/* === Tours Page === */
.tours-page-content {
padding: var(--space-xl) 0;
}

Reuse the .tours-grid and .tour-card from the global styles, extended with the more detailed card layout below.

/* === Detailed Tour Card (tours page) === */
.tour-card-image-wrap {
overflow: hidden;
}
.tour-card-image {
width: 100%;
aspect-ratio: 4 / 3;
object-fit: cover;
transition: transform var(--transition-normal);
}
.tour-card:hover .tour-card-image {
transform: scale(1.05);
}
.tour-card-body {
flex: 1;
padding: var(--space-md);
display: flex;
flex-direction: column;
}
.tour-card-title {
font-size: 1.25rem;
margin-bottom: var(--space-xs);
}
.tour-card-meta {
display: flex;
align-items: center;
gap: var(--space-md);
margin-bottom: var(--space-sm);
font-size: 0.85rem;
color: var(--color-text-muted);
}
.tour-card-meta-item {
display: flex;
align-items: center;
gap: var(--space-xs);
}
.tour-card-description {
color: var(--color-text-muted);
font-size: 0.95rem;
line-height: 1.6;
flex: 1;
margin-bottom: var(--space-md);
}
.tour-card-footer {
display: flex;
justify-content: space-between;
align-items: center;
padding-top: var(--space-sm);
border-top: 1px solid var(--color-border);
margin-top: auto;
}
.tour-price {
font-size: 1.25rem;
font-weight: 700;
color: var(--color-primary);
}
.tour-price-label {
font-size: 0.75rem;
color: var(--color-text-muted);
display: block;
font-weight: 400;
}

The .tour-card-footer uses justify-content: space-between to push the price to the left and the CTA button to the right — a common product listing pattern.

The hover state lifts the card and subtly zooms the image:

.tour-card {
/* ... existing styles from Lesson 01 ... */
transition: transform var(--transition-normal), box-shadow var(--transition-normal);
}
.tour-card:hover {
transform: translateY(-6px);
box-shadow: var(--shadow-lg);
}

The image zoom is handled by transform: scale(1.05) on .tour-card-image when the card is hovered — note the selector .tour-card:hover .tour-card-image targets the image inside a hovered card.

.tours-grid {
display: flex;
flex-direction: column;
gap: var(--space-md);
}
/* Two columns at tablet */
@media (min-width: 600px) {
.tours-grid {
flex-direction: row;
flex-wrap: wrap;
gap: var(--space-lg);
}
.tour-card {
flex: 1 1 calc(50% - var(--space-md));
}
}
/* Three columns at desktop */
@media (min-width: 1024px) {
.tour-card {
flex: 1 1 calc(33.333% - var(--space-lg));
}
}

Style the STO tours page:

  1. Add the page header, tour tag, and detailed card styles to styles.css.

  2. In tours.html, add the correct class names: .page-header, .tours-page-content, .tour-tags, .tour-tag, .tour-card-meta, .tour-card-footer.

  3. Wrap each tour card’s <img> in a <div class="tour-card-image-wrap"> and add class="tour-card-image" to the <img> itself:

    <div class="tour-card-image-wrap">
    <img class="tour-card-image" src="images/pine-ridge-loop.jpg" alt="Forested trail through cedar and fir trees on the Pine Ridge Loop">
    </div>

    The wrapper provides the overflow: hidden boundary that clips the zoom effect to the card edges. Without it, the scaled image bleeds outside the card on hover.

  4. Verify the card hover effect — the card should lift and the image should zoom. If the image still overflows on hover, confirm .tour-card-image-wrap has overflow: hidden and that .tour-card itself also has overflow: hidden set (it was added in the global card styles from Lesson 01).

  5. Test at 375px (one column), 700px (two columns), and 1100px (three columns). The grid should reflow cleanly at each breakpoint.

  6. Check that category tags wrap gracefully on mobile — flex-wrap: wrap on .tour-tags handles this.

  • .page-header is a reusable component — one CSS block styles the header on every interior page consistently.
  • Category tags use border-radius: var(--radius-full) (9999px) for the pill shape.
  • The .tour-card-meta row uses Flexbox with gap to display duration, difficulty, and other attributes horizontally.
  • transform: scale() on the image inside the hovered card requires overflow: hidden on the image wrapper to clip the zoom to the card boundary.
  • The calc() width approach gives precise column counts; the flex: 1 1 280px approach from Module 05 is equally valid and simpler.

Lesson 05 styles the blog listing and article pages — a different design challenge from marketing pages, focused on reading typography and comfortable line lengths.