What you will build
A landing page is a one-page website that introduces a product, a service or a person and invites a visitor to take one action: sign up, buy, call. You will take plain HTML and make it responsive and polished using what the course taught:
- CSS variables for colours, spacing and shape
box-sizing, a simple reset and readable typography- a header with Flexbox
- a hero with a gradient background and a call to action
- a features section with a responsive Grid
- a call-to-action band, and a footer
- a media query for wider screens
- transitions for hover and focus
The content here is a made-up "Sunrise Bakery" so you can focus on CSS. Change the words to your own project afterwards.
Step 1: the HTML
Start with clean semantic HTML and no styling. Paste this into the editor below:
<header class="site-header">
<a class="logo" href="#">Sunrise Bakery</a>
<nav aria-label="Main">
<a href="#menu">Menu</a>
<a href="#about">About</a>
<a href="#order" class="btn">Order now</a>
</nav>
</header>
<main>
<section class="hero">
<h1>Fresh bread, baked before sunrise</h1>
<p>Stone-ground flour, slow fermentation and nothing artificial.</p>
<a class="btn" href="#order">Order for pickup</a>
</section>
<section class="features" id="menu">
<h2>Why people love us</h2>
<div class="grid">
<article class="card"><h3>Slow fermented</h3><p>24 hours for deeper flavour and easier digestion.</p></article>
<article class="card"><h3>Local grain</h3><p>Flour milled within 50 km of the bakery.</p></article>
<article class="card"><h3>Baked daily</h3><p>Warm loaves on the counter from 6 a.m.</p></article>
</div>
</section>
<section class="cta" id="order">
<h2>Ready for tomorrow's loaf?</h2>
<a class="btn" href="#">Place an order</a>
</section>
</main>
<footer class="site-footer"><p>© 2026 Sunrise Bakery, 12 Market Road</p></footer>Step 2: variables and base styles
:root {
--brand: #c2410c;
--brand-dark: #9a3412;
--ink: #1f2937;
--paper: #fffaf5;
--card: #ffffff;
--space: 1rem;
--radius: 14px;
--shadow: 0 6px 20px rgb(0 0 0 / .08);
}
*, *::before, *::after { box-sizing: border-box; }
body {
margin: 0;
font-family: system-ui, sans-serif;
line-height: 1.6;
color: var(--ink);
background: var(--paper);
}
img { max-width: 100%; height: auto; }
h1, h2, h3 { line-height: 1.2; }Step 3: header, buttons and hero
.site-header {
display: flex;
flex-wrap: wrap;
align-items: center;
justify-content: space-between;
gap: var(--space);
padding: var(--space) calc(var(--space) * 1.5);
}
.logo { font-weight: 800; font-size: 1.25rem; color: var(--brand-dark); text-decoration: none; }
.site-header nav { display: flex; align-items: center; gap: var(--space); }
.site-header nav a { color: var(--ink); text-decoration: none; }
.btn {
display: inline-block;
padding: 0.7rem 1.4rem;
border-radius: 999px;
background: var(--brand);
color: white !important;
font-weight: 700;
text-decoration: none;
transition: background-color .2s ease, transform .2s ease;
}
.btn:hover { background: var(--brand-dark); transform: translateY(-2px); }
.btn:focus-visible { outline: 3px solid #fdba74; outline-offset: 3px; }
.hero {
padding: 4rem calc(var(--space) * 1.5);
text-align: center;
color: white;
background:
linear-gradient(rgb(0 0 0 / .35), rgb(0 0 0 / .35)),
linear-gradient(135deg, #f59e0b, #c2410c);
}
.hero h1 { font-size: clamp(2rem, 6vw, 3.5rem); margin: 0 0 .5rem; }
.hero p { max-width: 36rem; margin: 0 auto 1.5rem; font-size: 1.15rem; }Notice clamp(2rem, 6vw, 3.5rem): a heading that scales smoothly between a minimum and maximum with the screen width, with no media query. The dark overlay layer keeps the white text readable on the bright gradient.
Step 4: the responsive features grid
.features { padding: 3rem calc(var(--space) * 1.5); max-width: 70rem; margin-inline: auto; }
.features h2 { text-align: center; }
.grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
gap: calc(var(--space) * 1.5);
}
.card {
background: var(--card);
padding: calc(var(--space) * 1.5);
border-radius: var(--radius);
box-shadow: var(--shadow);
transition: transform .2s ease, box-shadow .2s ease;
}
.card:hover { transform: translateY(-4px); box-shadow: 0 12px 28px rgb(0 0 0 / .12); }
.card h3 { margin-top: 0; color: var(--brand-dark); }Step 5: call to action and footer
.cta {
text-align: center;
padding: 3rem calc(var(--space) * 1.5);
background: #ffedd5;
}
.site-footer { padding: var(--space); text-align: center; font-size: .9rem; background: #1f2937; color: #e5e7eb; }Step 6: wider screens and motion
Everything so far works on a phone. Add a layer for larger screens, and respect reduced motion:
@media (min-width: 48rem) {
.hero { padding: 7rem 2rem; }
.cta { display: flex; align-items: center; justify-content: center; gap: 2rem; }
.cta h2 { margin: 0; }
}
@media (prefers-reduced-motion: reduce) {
.btn, .card { transition: none; }
}The finished page
Put it all together here and experiment: change --brand and watch the whole page recolour.
<style>
:root { --brand:#c2410c; --brand-dark:#9a3412; --ink:#1f2937; --paper:#fffaf5; --card:#fff; --space:1rem; --radius:14px; --shadow:0 6px 20px rgb(0 0 0/.08); }
*,*::before,*::after{box-sizing:border-box}
body{margin:0;font-family:system-ui,sans-serif;line-height:1.6;color:var(--ink);background:var(--paper)}
.site-header{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:var(--space);padding:var(--space) 1.5rem}
.logo{font-weight:800;color:var(--brand-dark);text-decoration:none}
.site-header nav{display:flex;align-items:center;gap:var(--space)}
.site-header nav a{color:var(--ink);text-decoration:none}
.btn{display:inline-block;padding:.7rem 1.4rem;border-radius:999px;background:var(--brand);color:#fff!important;font-weight:700;text-decoration:none;transition:background-color .2s,transform .2s}
.btn:hover{background:var(--brand-dark);transform:translateY(-2px)}
.hero{padding:3rem 1.5rem;text-align:center;color:#fff;background:linear-gradient(rgb(0 0 0/.35),rgb(0 0 0/.35)),linear-gradient(135deg,#f59e0b,#c2410c)}
.hero h1{font-size:clamp(1.8rem,6vw,3rem);margin:0 0 .5rem}
.hero p{max-width:36rem;margin:0 auto 1.2rem}
.features{padding:2rem 1.5rem;max-width:70rem;margin-inline:auto}
.features h2{text-align:center}
.grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(13rem,1fr));gap:1.5rem}
.card{background:var(--card);padding:1.5rem;border-radius:var(--radius);box-shadow:var(--shadow);transition:transform .2s}
.card:hover{transform:translateY(-4px)}
.card h3{margin-top:0;color:var(--brand-dark)}
.cta{text-align:center;padding:2rem 1.5rem;background:#ffedd5}
.site-footer{padding:var(--space);text-align:center;font-size:.9rem;background:#1f2937;color:#e5e7eb}
@media (min-width:48rem){.cta{display:flex;align-items:center;justify-content:center;gap:2rem}.cta h2{margin:0}}
@media (prefers-reduced-motion:reduce){.btn,.card{transition:none}}
</style>
<header class="site-header"><a class="logo" href="#">Sunrise Bakery</a><nav aria-label="Main"><a href="#menu">Menu</a><a href="#about">About</a><a href="#order" class="btn">Order now</a></nav></header>
<main>
<section class="hero"><h1>Fresh bread, baked before sunrise</h1><p>Stone-ground flour, slow fermentation and nothing artificial.</p><a class="btn" href="#order">Order for pickup</a></section>
<section class="features" id="menu"><h2>Why people love us</h2><div class="grid">
<article class="card"><h3>Slow fermented</h3><p>24 hours for deeper flavour.</p></article>
<article class="card"><h3>Local grain</h3><p>Flour milled within 50 km.</p></article>
<article class="card"><h3>Baked daily</h3><p>Warm loaves from 6 a.m.</p></article>
</div></section>
<section class="cta" id="order"><h2>Ready for tomorrow's loaf?</h2><a class="btn" href="#">Place an order</a></section>
</main>
<footer class="site-footer">© 2026 Sunrise Bakery, 12 Market Road</footer>Check your work
- Narrow first: drag the preview narrow. Is everything readable with no sideways scroll?
- Wide: does the layout use the space sensibly? Do the cards reflow?
- Keyboard: Tab through the links and buttons. Is the focus ring always visible?
- Contrast: check the text against its backgrounds (white on the hero, the brand colour on the buttons) with the DevTools contrast checker. Aim for 4.5:1.
- Zoom to 200 per cent. Nothing should overlap.
- Reduced motion: confirm the page works with transitions turned off.
- Validate your HTML and CSS using the W3C validators.
Common mistakes
- Starting with desktop and fighting to squeeze it onto phones.
- Hard-coding every colour instead of using variables.
- Skipping the overlay on the hero and ending up with unreadable text.
- Fixed pixel widths for the grid.
- Forgetting focus styles because the mouse looks fine.
- Copying a template you do not understand, then being unable to change it.
Exercise
Add a "Testimonials" section between the features and the call to action: two quote cards in a two-column Grid on wide screens and one column on narrow ones, using the same variables.
Show one possible answer
<style>
.quotes { padding: 3rem 1.5rem; max-width: 70rem; margin-inline: auto; }
.quotes .grid { display: grid; gap: 1.5rem; }
@media (min-width: 48rem) { .quotes .grid { grid-template-columns: 1fr 1fr; } }
blockquote { margin: 0; padding: 1.5rem; background: var(--card); border-left: 5px solid var(--brand); border-radius: var(--radius); box-shadow: var(--shadow); }
</style>
<section class="quotes">
<h2>What neighbours say</h2>
<div class="grid">
<blockquote>"The best crust in the city." <footer>Asha</footer></blockquote>
<blockquote>"We order every Saturday." <footer>Kabir</footer></blockquote>
</div>
</section>Use real, permitted quotes on a real site, never invented ones.
You have finished the CSS course. Next, put your pages online and keep practising by rebuilding pages you admire from scratch.
Key points
- The project combines the course - variables, box-sizing, Flexbox, Grid, media queries, backgrounds and transitions.
- Build it mobile-first - style the narrow layout first, then add rules for wider screens.
- Define your colours, spacing and radius as variables before writing any component styles.
- Check contrast, keyboard focus and reduced motion before you call the page finished.
- A small page you finish and understand is worth more than a big template you copied.
Check yourself
Free tools for this lesson
Final exam and certificate
Finish all 29 lessons to unlock a 15-question exam on CSS. Pass it and you get a certificate with a public link you can share.
Sign in to take the exam