12 — Foundation

🏗 Chapter 12 — Foundation

This is the first of eight chapters that make up the CSS Beginner capstone project. Rather than introducing new properties, we apply everything from Chapters 1–11 to build a complete, professional, responsive landing page for a fictional creative agency called Lumen Studio. By the end of Chapter 19 you will have a page you can deploy as-is or adapt into your own portfolio.

The project is split across eight chapters so each one stays a manageable size:

  • Chapter 12 (this chapter) — Project intro, HTML structure, and CSS Steps 1–3: foundation variables, reset, utilities, and buttons.
  • Chapter 13 — Navigation and the hero section.
  • Chapter 14 — Content bands: clients strip, services grid, and stats bar.
  • Chapter 15 — The About section.
  • Chapter 16 — Testimonials.
  • Chapter 17 — The CTA section and footer.
  • Chapter 18 — Bringing it to life: scroll reveal and nav-shadow JavaScript.
  • Chapter 19 — Go Further: a wrap-up and five extension challenges.

1 — What We're Building

Lumen Studio is a single-page marketing site for a creative design agency. It uses a clean light theme (white background, dark navy text, blue accent) with a dark navy footer and stats section for contrast. Every major layout and styling technique from the course appears somewhere on the page.

Page structure — wireframe overview
lumen.studio
Navigation — sticky header Ch.6 display · Ch.7 position:sticky · Ch.8 Flexbox · Ch.10 transition
Hero — text column
h1 · clamp() · flex actions
✦ Brand Strategy
◈ UI / UX Design
⬡ Development
Hero — 2-col Grid Ch.9 Grid · Ch.10 @keyframes animation · Ch.11 clamp() + responsive
Clients strip Ch.8 Flexbox
Services — 6-card auto-fit grid Ch.9 Grid auto-fit · Ch.10 hover transition · Ch.7 ::before
Brand Strategy
UI / UX
Development
Growth & SEO
Mobile
Support
Stats bar — dark background Ch.4 background · Ch.9 Grid · Ch.11 clamp()
About — image + badge
position:absolute badge
About — text + checklist
::before checkmarks
About — 2-col Grid Ch.7 position:absolute · Ch.9 Grid · Ch.5 Typography
Testimonials — 3-card auto-fit grid Ch.9 Grid · Ch.3 Box Model
CTA — dark gradient + pseudo-element circles Ch.4 gradient · Ch.7 position:absolute ::before/::after

Skills used — chapter map

Page sectionCSS techniqueTaught in
Entire pageCSS custom properties (:root variables)Ch.9
All textTypography, clamp(), rem, line-heightCh.5 Ch.11
All spacingBox model: margin, padding, gapCh.3
Colors & gradientsCustom properties, rgba(), linear-gradient()Ch.4
Buttonsdisplay: inline-flex, transition, transformCh.6 Ch.10
Navigationposition: sticky, Flexbox, backdrop-filterCh.7 Ch.8
HeroCSS Grid 2-col, @keyframes float animationCh.9 Ch.10
Services, TestimonialsGrid auto-fit / minmax()Ch.9
Service card top bar::before pseudo-element + transform: scaleX()Ch.10
About badgeposition: absolute on a position: relative parentCh.7
CTA circles::before / ::after decorative elementsCh.7
FooterGrid auto-fit, Flexbox footer-bottomCh.9 Ch.8
Responsive layoutViewport meta, clamp(), @media (min-width)Ch.11
Scroll revealIntersectionObserver + CSS opacity / transform transitionCh.10

2 — File Structure

The project uses three files. Keep them in the same folder so the relative paths work without any configuration.

lumen-studio/ ├── index.html ← The page markup ├── style.css ← All CSS (built across Chapters 12–18) └── main.js ← Two small JavaScript helpers (Chapter 18)
Working in VS Code? Install the Live Server extension (right-click index.html → "Open with Live Server"). It auto-refreshes the browser every time you save — essential for a CSS-heavy project like this.

3 — The HTML

Build this first. The HTML is the skeleton — we add no CSS yet. Every class name here will be targeted across Chapters 12–17. Read the comments carefully; they are your map through the CSS walkthrough that follows.

🌐 index.html — complete page markup
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Lumen Studio — Creative Design Agency</title> <link rel="stylesheet" href="style.css"> </head> <body> <!-- ── NAVIGATION ─────────────────────────────────── --> <header class="site-header"> <nav class="nav container"> <a href="#" class="nav-logo">Lumen<span>.</span></a> <ul class="nav-links"> <li><a href="#services">Services</a></li> <li><a href="#about">About</a></li> <li><a href="#work">Work</a></li> <li><a href="#contact">Contact</a></li> </ul> <a href="#contact" class="btn btn-primary btn-sm">Start a project</a> <button class="hamburger" aria-label="Open menu"></button> </nav> </header> <!-- ── HERO ───────────────────────────────────────── --> <section class="hero"> <div class="container hero-inner"> <div class="hero-text"> <span class="hero-eyebrow">Creative Studio</span> <h1>We design brands that <em>stand out</em></h1> <p>Award-winning design and development for companies that want to be remembered.</p> <div class="hero-actions"> <a href="#work" class="btn btn-primary btn-lg">See our work</a> <a href="#about" class="btn btn-ghost">Learn more</a> </div> </div> <div class="hero-visual" aria-hidden="true"> <div class="h-card h-card--a"> <div class="h-card-icon"></div> <div class="h-card-title">Brand Strategy</div> <div class="h-card-sub">Identity · Positioning · Voice</div> </div> <div class="h-card h-card--b"> <div class="h-card-icon"></div> <div class="h-card-title">UI / UX Design</div> <div class="h-card-sub">Web · Mobile · Systems</div> </div> <div class="h-card h-card--c"> <div class="h-card-icon"></div> <div class="h-card-title">Development</div> <div class="h-card-sub">React · Next.js · CMS</div> </div> </div> </div> </section> <!-- ── CLIENTS STRIP ──────────────────────────────── --> <div class="clients"> <div class="container clients-inner"> <span class="clients-label">Trusted by</span> <div class="clients-logos"> <span class="client-logo">Meridian</span> <span class="client-logo">Vantage</span> <span class="client-logo">Halcyon</span> <span class="client-logo">Prism</span> <span class="client-logo">Solaris</span> </div> </div> </div> <!-- ── SERVICES ───────────────────────────────────── --> <section class="services" id="services"> <div class="container"> <div class="services-header reveal"> <span class="section-label">What we do</span> <h2 class="section-title">Everything you need to grow</h2> <p class="section-sub">From brand discovery through to launch and beyond.</p> </div> <div class="services-grid"> <div class="s-card reveal"><div class="s-icon">🎯</div><h3>Brand Strategy</h3> <p>We help you find and own your place in the market.</p></div> <div class="s-card reveal"><div class="s-icon">🎨</div><h3>UI / UX Design</h3> <p>Intuitive interfaces that guide users to what matters.</p></div> <div class="s-card reveal"><div class="s-icon"></div><h3>Web Development</h3> <p>Fast, accessible builds in React, Next.js or your stack.</p></div> <div class="s-card reveal"><div class="s-icon">📈</div><h3>Growth & SEO</h3> <p>Content strategy that turns visitors into customers.</p></div> <div class="s-card reveal"><div class="s-icon">📱</div><h3>Mobile Design</h3> <p>Native-feeling experiences with craft users expect.</p></div> <div class="s-card reveal"><div class="s-icon">🔧</div><h3>Ongoing Support</h3> <p>Monthly retainers so your presence keeps evolving.</p></div> </div> </div> </section> <!-- ── STATS ───────────────────────────────────────── --> <section class="stats"> <div class="container stats-grid"> <div class="stat reveal"><span class="stat-num">140+</span><span class="stat-label">Projects delivered</span></div> <div class="stat reveal"><span class="stat-num">98%</span><span class="stat-label">Client satisfaction</span></div> <div class="stat reveal"><span class="stat-num">12</span><span class="stat-label">Industry awards</span></div> <div class="stat reveal"><span class="stat-num">8yr</span><span class="stat-label">In business</span></div> </div> </section> <!-- ── ABOUT ───────────────────────────────────────── --> <section class="about" id="about"> <div class="container about-inner"> <div class="about-image-wrap reveal"> <div class="about-img">🎨</div> <div class="about-badge"> <span class="badge-num">8+</span> Years of craft </div> </div> <div class="about-text reveal"> <span class="section-label">About us</span> <h2>A small studio with big ambitions</h2> <p>We're a tight-knit team of designers, developers, and strategists who believe thoughtful craft and commercial results reinforce each other.</p> <p>Every project is a partnership. We ask the awkward questions and sweat the small details most agencies skip.</p> <ul class="about-checklist"> <li>Dedicated project lead on every engagement</li> <li>Weekly progress calls and shared Figma access</li> <li>Fixed-price packages — no surprise invoices</li> <li>Post-launch support included as standard</li> </ul> <a href="#contact" class="btn btn-primary">Work with us</a> </div> </div> </section> <!-- ── TESTIMONIALS ────────────────────────────────── --> <section class="testimonials"> <div class="container"> <div class="testi-header reveal"> <span class="section-label">Testimonials</span> <h2 class="section-title">What our clients say</h2> <p class="section-sub">We let the work speak — then let the clients speak for the work.</p> </div> <div class="testi-grid"> <div class="t-card reveal"> <div class="t-stars">★★★★★</div> <blockquote>The best creative decision we made this year. On time, on budget, beyond expectation.</blockquote> <div class="t-author"> <div class="t-avatar">SA</div> <div class="t-author-info"> <strong>Sarah Adeyemi</strong><span>CEO, Meridian Labs</span> </div> </div> </div> <div class="t-card reveal"> <div class="t-stars">★★★★★</div> <blockquote>They redesigned how we think about our digital presence. Conversion rates are up 34%.</blockquote> <div class="t-author"> <div class="t-avatar">JK</div> <div class="t-author-info"> <strong>James Kowalski</strong><span>Head of Product, Vantage</span> </div> </div> </div> <div class="t-card reveal"> <div class="t-stars">★★★★★</div> <blockquote>Extraordinary attention to detail. Every micro-interaction felt considered.</blockquote> <div class="t-author"> <div class="t-avatar">ML</div> <div class="t-author-info"> <strong>Maria Leclaire</strong><span>Design Director, Halcyon</span> </div> </div> </div> </div> </div> </section> <!-- ── CTA ────────────────────────────────────────── --> <section class="cta-section" id="contact"> <div class="container cta-inner reveal"> <span class="section-label" style="color: rgba(255,255,255,0.5)">Get started</span> <h2>Ready to build something great?</h2> <p>Tell us about your project. We'll reply within one business day.</p> <a href="mailto:hello@lumen.studio" class="btn btn-white btn-lg">Start a project →</a> </div> </section> <!-- ── FOOTER ─────────────────────────────────────── --> <footer class="site-footer"> <div class="container footer-grid"> <div class="footer-brand"> <a href="#" class="nav-logo">Lumen<span>.</span></a> <p>Creative studio in London, working worldwide.</p> </div> <div class="footer-col"> <h4>Services</h4> <ul> <li><a href="#">Brand Strategy</a></li> <li><a href="#">UI / UX Design</a></li> <li><a href="#">Web Development</a></li> <li><a href="#">Growth & SEO</a></li> </ul> </div> <div class="footer-col"> <h4>Company</h4> <ul> <li><a href="#">About</a></li> <li><a href="#">Work</a></li> <li><a href="#">Careers</a></li> <li><a href="#">Blog</a></li> </ul> </div> <div class="footer-col"> <h4>Contact</h4> <ul> <li><a href="mailto:hello@lumen.studio">hello@lumen.studio</a></li> <li><a href="#">+44 20 7946 0000</a></li> <li><a href="#">London, UK</a></li> </ul> </div> </div> <div class="container footer-bottom"> <p>© 2026 Lumen Studio Ltd.</p> <div><a href="#">Privacy</a> &nbsp;<a href="#">Terms</a></div> </div> </footer> <script src="main.js"></script> </body> </html>
The reveal class is added to elements that will fade in as the user scrolls. It does nothing until JavaScript activates it in Chapter 18 — so leave it on now and the page will look fine without the JS, just without scroll animations.
💡 Open the page now — Before writing any CSS, open index.html in your browser. You'll see unstyled plain text. That's correct. Every CSS step across Chapters 12–17 progressively improves what you see, which is the best way to understand what each block of CSS actually does.
1
Custom Properties & Reset → style.css

The first block in style.css does two things: it defines all colours, fonts, and sizes as CSS variables (so changing one value updates the whole page), and it strips the browser's built-in default styles so we start from a clean baseline.

🎨 style.css — Step 1: Custom properties and reset
/* ── Custom properties ───────────────────────────── */ :root { /* Colours */ --clr-bg: #ffffff; --clr-bg-alt: #f7f8fc; --clr-dark: #0d1117; --clr-navy: #111827; --clr-text: #1f2937; --clr-muted: #6b7280; --clr-border: #e5e7eb; --clr-accent: #4f8ef7; --clr-accent-dark: #3a7ae0; /* Font */ --font: system-ui, -apple-system, sans-serif; /* Reused values */ --radius: 10px; --container: 1200px; } /* ── Reset ───────────────────────────────────────── */ *, *::before, *::after { box-sizing: border-box; /* padding/border inside width — always */ margin: 0; padding: 0; } img, video { max-width: 100%; height: auto; display: block; } ul { list-style: none; } a { text-decoration: none; color: inherit; } button { font-family: inherit; cursor: pointer; } body { font-family: var(--font); color: var(--clr-text); background-color: var(--clr-bg); line-height: 1.6; -webkit-font-smoothing: antialiased; /* crisper text on Mac/iOS */ }
Defining colours as :root variables means you can completely rebrand the page by changing 9 values. Try swapping --clr-accent to #e85d3f and watch the entire page update.
2
Utility Classes → style.css

These three classes are reused throughout the page. Defining them once here prevents repetition across every section. .container is especially important — it applies the max-width + margin: auto centering pattern from Chapter 11 to every section consistently.

🎨 style.css — Step 2: Utility classes
/* ── Container — centered, max-width, fluid padding ─ */ .container { max-width: var(--container); /* 1200px — never wider */ margin: 0 auto; /* horizontally centered */ padding: 0 clamp(1rem, 4vw, 2.5rem); /* fluid side padding */ } /* ── Section typography helpers ──────────────────── */ .section-label { display: inline-block; font-size: 0.75rem; font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase; color: var(--clr-accent); margin-bottom: 0.6rem; } .section-title { font-size: clamp(1.6rem, 3.5vw, 2.5rem); font-weight: 700; color: var(--clr-dark); margin-bottom:0.6rem; line-height: 1.2; } .section-sub { color: var(--clr-muted); max-width: 55ch; line-height:1.7; }
3
Button System → style.css

Buttons appear in the nav, hero, about section, and CTA. Defining a base .btn class plus modifier classes (.btn-primary, .btn-ghost, .btn-white, .btn-lg, .btn-sm) means any element can become any button variant just by adding HTML classes — no duplicated CSS.

🎨 style.css — Step 3: Button system
/* ── Base button ─────────────────────────────────── */ .btn { display: inline-flex; /* icon + text alignment */ align-items: center; gap: 0.4em; padding: 0.65em 1.4em; border-radius: 6px; font-weight: 600; font-size: 0.95rem; border: 2px solid transparent; white-space: nowrap; transition: background 0.2s ease, transform 0.15s ease, box-shadow 0.2s ease, border-color 0.2s ease, color 0.2s ease; } .btn:hover { transform: translateY(-2px); } /* ── Variants ────────────────────────────────────── */ .btn-primary { background: var(--clr-accent); color: #fff; } .btn-primary:hover { background: var(--clr-accent-dark); box-shadow: 0 6px 20px rgba(79, 142, 247, 0.35); } .btn-ghost { background: transparent; border-color: var(--clr-border); color: var(--clr-text); } .btn-ghost:hover { border-color: var(--clr-accent); color: var(--clr-accent); } .btn-white { background: #fff; color: var(--clr-accent); } .btn-white:hover { box-shadow: 0 8px 24px rgba(0, 0, 0, 0.15); } /* ── Size modifiers ──────────────────────────────── */ .btn-lg { padding: 0.8em 2em; font-size: 1.05rem; } .btn-sm { padding: 0.45em 1em; font-size: 0.85rem; }
Live button preview — hover to see the transitions
💡 Why inline-flex on a button? It keeps the button as an inline element (so it sits in text flow and sizes to its content) while enabling Flexbox alignment internally. This is how you get an icon and label perfectly vertically centred without extra positioning tricks — a pattern used in almost every real-world component library.
Next — Chapter 13: The navigation bar and hero sectionposition: sticky, a two-column Grid, and floating @keyframes animations.