Capstone project

Capstone: an article page for everyone

Lesson 20 of 20 · 30 min · Module 6: Fast pages and the capstone

Bring everything together in a real article page: keyboard friendly, readable, light and dark, responsive down to small phones, calm for people who prefer less motion, and clean on paper.

Start this lesson →

Free. No installation: you write and run the code in your browser, and it is checked automatically.

By the end, you’ll be able to…

  • Combine accessibility, theming and responsive layout in one page
  • Check a page in several situations: keyboard, phone, dark mode, print
  • Work in small, verified steps

The idea

The markup is provided. Your job is the finishing work that separates a page that works from a page that works for everyone. Build it in small steps and run the checks often.

/* Suggested order */
1. Skip link, landmarks and the current page
2. Theme variables, light and dark
3. Sticky header, readable article, responsive figure
4. Related cards grid
5. Focus, reduced motion and print

01Start with structure

The skip link, the main id, the navigation name and aria-current change no pixels for most visitors, yet they decide whether keyboard and screen reader users can use the page at all.

02Then the system of values

Defining the theme variables before anything else means every later rule can use them, and dark mode works automatically for each new part you add.

03Finally, the situations

Test the page as different people experience it: with only the keyboard, on a 390px screen, in dark mode, with reduced motion, and in print preview. Each check in this capstone corresponds to one of those situations.

Keyboard: Tab → skip link → header links → article
Phone:    no sideways scrolling, one column of cards
Dark:     variables switch, text stays readable
Print:    header and related links hidden

Your project brief

Complete the page:
• Skip link: give the first link the class skip-link and href="#main", give main the id main, hide the link with position: absolute; top: -48px; left: 16px; and show it with .skip-link:focus-visible { top: 8px; };
• Navigation: add aria-label="Main" to nav and aria-current="page" to the Blog link;
• Theme: on :root define --bg: #ffffff; --text: #1f2a24; --surface: #f4f7ef; --accent: #2f6f4e; and color-scheme: light dark; inside @media (prefers-color-scheme: dark) use --bg: #141a16; --text: #e6efe4; --surface: #1f2822; --accent: #8fd18f;; give body background: var(--bg); color: var(--text); margin: 0;;
• Header: .site-header { position: sticky; top: 0; background: var(--bg); display: flex; flex-wrap: wrap; gap: 12px; justify-content: space-between; padding: 12px 16px; };
• Article: main { padding: 16px; } and .article { max-inline-size: 65ch; margin-inline: auto; };
• Figure: give the image a meaningful alt text and width="1200" height="675"; style .photo img { width: 100%; height: auto; aspect-ratio: 16 / 9; object-fit: cover; };
• Related: .related-list { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 220px), 1fr)); gap: 16px; } and .card { background: var(--surface); border-radius: 12px; padding: 16px; transition: transform 200ms ease; };
• Focus: a:focus-visible { outline: 3px solid var(--accent); outline-offset: 2px; };
• Motion: inside @media (prefers-reduced-motion: reduce), .card { transition: none; };
• Print: inside @media print, hide .site-header, .related and .skip-link.

What the checks look for

  • A skip link is the first element and points to #main
  • main has the id main
  • The skip link appears on keyboard focus
  • The main navigation is named and marks the current page
  • Light theme colours are defined on :root
  • Dark theme colours apply when people prefer dark
  • The page background uses the theme
  • Cards use the surface colour
  • The header sticks to the top
  • The article keeps a readable line length
  • The photo has alt text and reserved space
  • The photo keeps a 16:9 shape
  • Related cards stack on a phone
  • Related cards sit side by side at 900px
  • Links show a clear focus outline
  • Reduced motion removes the card transition
  • The header is hidden on paper
  • Related articles are hidden on paper
  • The header fits a phone screen
  • The main content fits a phone screen
Try it in the editor →

Take this with you

A page is finished when it works for everyone, not just on your screen.

Go a little further

Add a theme toggle: a button that sets data-theme="dark" on the html element with three lines of JavaScript, and a [data-theme="dark"] rule with the dark values.

Learn HTML & CSS Intermediate for free

20 short lessons with real code and instant checks.

See the whole course →