CSS · Practice

Responsive Website Project

Time to put it all together. You will build a complete, responsive landing page using everything from the CSS track: variables, Flexbox, Grid, media queries and transitions.

Advanced 7 min Lesson 25 of 26 Runnable examples
0/26 in CSS
On this page · 7 min · Advanced

Learning objectives#

  • Plan a page as sections and components
  • Build mobile-first with CSS variables
  • Use Flexbox for the header and Grid for features and pricing
  • Add hover states, focus styles and a responsive breakpoint
  • Check the result for accessibility

Explanation#

Step 1 — HTML first: header (logo + nav), main with hero, features and pricing sections, footer. Semantic and valid before any CSS.

Step 2 — Tokens: colours, spacing and radius as CSS variables on :root.

Step 3 — Base: reset, body font, fluid images, a .container with max-width.

Step 4 — Components: header with Flexbox; hero with clamp() heading; features with auto-fit Grid; pricing cards with a featured modifier.

Step 5 — Polish: a breakpoint for the nav, hover transitions, :focus-visible, reduced motion. Then test at 320px, 768px and 1280px.

Code example: Complete responsive landing page#

HTMLComplete responsive landing page Runnable
<style>
  :root { --brand:#4f46e5; --text:#0f172a; --muted:#64748b; --bg:#f8fafc; --radius:14px; --space:clamp(1rem, 3vw, 2rem); }
  *, *::before, *::after { box-sizing: border-box; margin: 0; }
  body { font-family: system-ui, sans-serif; color: var(--text); background: var(--bg); line-height: 1.6; }
  .container { width: min(100% - 2rem, 1100px); margin-inline: auto; }


  .header { display: flex; flex-wrap: wrap; gap: 1rem; justify-content: space-between; align-items: center; padding-block: 1rem; }
  .logo { font-weight: 800; color: var(--brand); }
  .nav { display: flex; gap: 1rem; list-style: none; padding: 0; }
  .nav a { color: var(--text); text-decoration: none; }
  .nav a:hover { color: var(--brand); }


  .hero { text-align: center; padding-block: var(--space); }
  .hero h1 { font-size: clamp(1.8rem, 6vw, 3.2rem); line-height: 1.15; margin-bottom: .5rem; }
  .hero p { color: var(--muted); max-width: 55ch; margin: 0 auto 1.25rem; }
  .btn { display: inline-block; background: var(--brand); color: white; padding: .75rem 1.5rem; border-radius: 999px; text-decoration: none; transition: transform 150ms, box-shadow 150ms; }
  .btn:hover { transform: translateY(-2px); box-shadow: 0 8px 20px rgb(79 70 229 / 30%); }
  :focus-visible { outline: 3px solid #f59e0b; outline-offset: 3px; }


  .section-title { text-align: center; margin: var(--space) 0 1rem; }
  .grid { display: grid; gap: 1rem; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); }
  .card { background: white; border: 1px solid #e2e8f0; border-radius: var(--radius); padding: 1.25rem; }
  .card--featured { border: 2px solid var(--brand); }
  .price { font-size: 2rem; font-weight: 800; }


  .footer { margin-top: var(--space); padding-block: 1.5rem; text-align: center; color: var(--muted); }


  @media (max-width: 480px) { .nav { width: 100%; justify-content: space-between; } }
  @media (prefers-reduced-motion: reduce) { * { transition: none !important; } }
</style>


<div class="container">
  <header class="header">
    <span class="logo">TaskFlow</span>
    <nav aria-label="Main"><ul class="nav"><li><a href="#features">Features</a></li><li><a href="#pricing">Pricing</a></li><li><a href="#">Login</a></li></ul></nav>
  </header>


  <main>
    <section class="hero">
      <h1>Organise your work.<br>Finish on time.</h1>
      <p>TaskFlow keeps your team’s tasks, deadlines and files in one simple place.</p>
      <a class="btn" href="#pricing">Start free</a>
    </section>


    <section id="features">
      <h2 class="section-title">Features</h2>
      <div class="grid">
        <article class="card"><h3>📋 Boards</h3><p>Drag tasks between columns.</p></article>
        <article class="card"><h3>⏰ Reminders</h3><p>Never miss a deadline.</p></article>
        <article class="card"><h3>👥 Teams</h3><p>Share projects with anyone.</p></article>
      </div>
    </section>


    <section id="pricing">
      <h2 class="section-title">Pricing</h2>
      <div class="grid">
        <article class="card"><h3>Free</h3><p class="price">₹0</p><p>Up to 3 projects</p></article>
        <article class="card card--featured"><h3>Pro</h3><p class="price">₹299</p><p>Unlimited projects</p></article>
        <article class="card"><h3>Team</h3><p class="price">₹999</p><p>Up to 20 members</p></article>
      </div>
    </section>
  </main>


  <footer class="footer">© 2026 TaskFlow</footer>
</div>
Expected output
A full landing page: header with logo and links, a centred hero with a call-to-action button, a feature grid and pricing cards that reflow from three columns to one as the screen narrows.
Opens this example in the full playground

Step-by-step explanation#

  1. Design tokens live on :root, so a rebrand is one line.
  2. The reset and .container give consistent spacing and a centred, fluid width.
  3. The header uses Flexbox with space-between and wraps on small screens.
  4. The hero heading scales with clamp(); the paragraph is limited to 55ch.
  5. Features and pricing reuse the same auto-fit Grid and .card component.
  6. .card--featured highlights the recommended plan.
  7. A small media query adjusts the nav on very narrow phones; reduced motion turns off transitions.

Real-world use case#

This is the structure of real SaaS, course and product landing pages. Add it to your portfolio, then extend it with a contact form and a dark theme.

Common mistakes#

Building desktop first

Starting at 1280px and squeezing down leads to many overrides. Start from the narrow layout.

Copying values everywhere

Hard-coding #4f46e5 in 15 places makes changes painful. Use variables.

Skipping testing

Check at 320px, 768px and 1280px, use only the keyboard once, and run Lighthouse.

Best practices#

  • Write the HTML completely before the CSS
  • Reuse components (card, btn) with modifiers
  • Prefer intrinsic layouts, add media queries only when needed
  • Run Lighthouse and fix accessibility issues
  • Deploy it (GitHub Pages or Hostinger) and share the link

Remember this#

Order of work: HTML → tokens → base → components → responsive → polish → test.

One .card + modifiers beats three different card styles.

Test small, medium, large — and with the keyboard.

Practice exercise#

Your task: Extend the page: add a dark theme using prefers-color-scheme by redefining only the colour variables.

Need a hint?
Override --text, --muted and --bg, and make .card background a variable too.
Show solution
CSS Illustrative
@media (prefers-color-scheme: dark) {
  :root {
    --text: #e2e8f0;
    --muted: #94a3b8;
    --bg: #0f172a;
  }
  .card { background: #1e293b; border-color: #334155; }
  .nav a { color: var(--text); }
}

Mini quiz#

Responsive Website Project quizMultiple choice Question 1 of 3

Which layout tool suits the header (logo left, links right)?

Score so far: 0/0

Want more? Practise all CSS MCQs · CSS interview questions

My notes#

Saved in this browser.

Progress is saved in this browser. Sign in to sync.