🧭 Chapter 13 — Navigation & Hero
Chapter 12 laid the foundation: custom properties, reset, utility classes, and the button system. This chapter builds the first two things a visitor actually sees — the sticky navigation bar and the hero section. Add each step's CSS to your style.css below the code from Chapter 12. Save and refresh after each step to see the page take shape.
The nav uses position: sticky so it stays at the top of the screen as the user scrolls (Chapter 7). The inner .nav element is a Flexbox row that pushes the logo to the left and the links+button to the right with justify-content: space-between (Chapter 8). On mobile the nav links are hidden with display: none and replaced by a hamburger button — a single @media query at 768px reverses this (Chapter 11). The backdrop-filter: blur() creates the frosted-glass effect as page content scrolls beneath the bar.
/* ── Sticky header shell ─────────────────────────── */
.site-header {
position: sticky;
top: 0;
z-index: 100; /* sits above all page content */
background: rgba(255, 255, 255, 0.85);
backdrop-filter: blur(12px); /* frosted-glass effect */
-webkit-backdrop-filter: blur(12px); /* Safari prefix */
border-bottom: 1px solid var(--clr-border);
transition: box-shadow 0.2s;
}
/* Added by JavaScript once the user scrolls — deeper shadow */
.site-header.scrolled {
box-shadow: 0 2px 16px rgba(0, 0, 0, 0.08);
}
/* ── Nav row — Flexbox ───────────────────────────── */
.nav {
display: flex;
align-items: center;
justify-content: space-between;
gap: 2rem;
height: 68px; /* fixed height — consistent feel */
}
/* ── Logo ────────────────────────────────────────── */
.nav-logo {
font-weight: 800;
font-size: 1.3rem;
color: var(--clr-dark);
letter-spacing: -0.02em;
}
.nav-logo span { color: var(--clr-accent); } /* blue dot */
/* ── Nav links — hidden on mobile ────────────────── */
.nav-links {
display: none; /* hidden until 768px breakpoint */
align-items:center;
gap: 1.75rem;
}
.nav-links a {
font-size: 0.9rem;
font-weight:500;
color: var(--clr-muted);
transition:color 0.2s;
}
.nav-links a:hover { color: var(--clr-text); }
/* ── Hamburger — shown on mobile only ────────────── */
.hamburger {
display: flex;
align-items: center;
justify-content:center;
background: none;
border: 1px solid var(--clr-border);
border-radius:6px;
padding: 0.4em 0.6em;
font-size: 1.1rem;
color: var(--clr-text);
transition: border-color 0.2s;
}
.hamburger:hover { border-color: var(--clr-accent); }
/* ── Responsive: tablet+ shows links, hides hamburger */
@media (min-width: 768px) {
.nav-links { display: flex; }
.hamburger { display: none; }
}
.scrolled class is applied by a 3-line JavaScript snippet in Chapter 18. Without it the nav looks fine — the border-bottom alone separates it from the page. The JS shadow is a polish detail, not a requirement for the layout.z-index: 100 guarantees the nav always wins without needing to guess what other stacking contexts exist on the page.
The hero is the most complex section — it combines several techniques at once. The outer .hero has a subtle diagonal gradient background and generous clamp() padding that scales from comfortable on mobile to dramatic on desktop. Inside, .hero-inner is a CSS Grid that stacks on mobile and splits into two columns (text left, cards right) at 900px. The three floating cards use @keyframes animations with different durations and alternate direction to create a natural, unsynchronised floating effect.
/* ── Section shell ───────────────────────────────── */
.hero {
padding: clamp(5rem, 12vw, 10rem) 0 clamp(4rem, 8vw, 7rem);
background: linear-gradient(160deg, #eef3ff 0%, #ffffff 55%);
overflow: hidden; /* card animations can't escape the section */
}
/* ── Two-column grid ─────────────────────────────── */
.hero-inner {
display: grid;
gap: 3rem;
align-items: center;
}
@media (min-width: 900px) {
.hero-inner { grid-template-columns: 1.15fr 1fr; }
}
/* ── Eyebrow pill ────────────────────────────────── */
.hero-eyebrow {
display: inline-flex;
align-items: center;
gap: 0.5em;
font-size: 0.78rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.1em;
color: var(--clr-accent);
background: rgba(79, 142, 247, 0.1);
padding: 0.35em 0.9em;
border-radius: 999px;
margin-bottom: 1.25rem;
}
.hero-eyebrow::before { /* small blue dot */
content: '';
width: 6px;
height: 6px;
border-radius: 50%;
background: var(--clr-accent);
}
/* ── Heading ─────────────────────────────────────── */
.hero-text h1 {
font-size: clamp(2.5rem, 5.5vw, 4.25rem);
font-weight: 800;
line-height: 1.08;
color: var(--clr-dark);
letter-spacing:-0.03em;
margin-bottom: 1.25rem;
}
.hero-text h1 em {
font-style: normal;
color: var(--clr-accent); /* blue highlight word */
}
/* ── Subheading ──────────────────────────────────── */
.hero-text > p {
font-size: clamp(1rem, 2vw, 1.2rem);
color: var(--clr-muted);
max-width: 48ch;
line-height: 1.7;
margin-bottom:2rem;
}
/* ── CTA button row ──────────────────────────────── */
.hero-actions {
display: flex;
gap: 1rem;
flex-wrap: wrap; /* buttons wrap on very narrow screens */
}
/* ── Floating cards grid ─────────────────────────── */
.hero-visual {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 1rem;
padding: 1rem;
}
.h-card {
background: #fff;
border: 1px solid var(--clr-border);
border-radius:12px;
padding: 1.25rem 1.5rem;
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.06);
transition: transform 0.35s ease, box-shadow 0.35s ease;
}
.h-card:hover {
transform: translateY(-5px);
box-shadow: 0 16px 32px rgba(0, 0, 0, 0.1);
}
/* Card A spans full width (both columns) */
.h-card--a {
grid-column: 1 / -1;
animation: floatUp 5s ease-in-out infinite alternate;
}
.h-card--b { animation: floatDown 6s ease-in-out infinite alternate; }
.h-card--c { animation: floatUp 4.5s 0.5s ease-in-out infinite alternate; }
.h-card-icon { font-size: 1.5rem; margin-bottom: 0.5rem; }
.h-card-title { font-weight: 700; font-size: 0.95rem; color: var(--clr-dark); margin-bottom: 0.2rem; }
.h-card-sub { font-size: 0.78rem; color: var(--clr-muted); }
/* ── Float keyframes ─────────────────────────────── */
@keyframes floatUp {
from { transform: translateY(0); }
to { transform: translateY(-10px); }
}
@keyframes floatDown {
from { transform: translateY(0); }
to { transform: translateY(8px); }
}
We design brands that stand out
Award-winning design and development for companies that want to be remembered.
How the float animation works
Three cards, three separate animations — different durations (5s, 6s, 4.5s) and different offsets (card C has a 0.5s delay) — mean they never move in perfect sync. alternate makes the animation reverse direction at the end of each cycle instead of jumping back to the start, creating a smooth infinite loop. ease-in-out makes each float feel organic rather than mechanical.
auto-fit grid pattern.