Skip to the content

CSS project 2 final code, the complete website header with menu

Last updated: By Lukas BrandtLesson 21 of 215 min read

This is the whole of Project 2 in one place: the HTML from lesson 16, which never changed, and every CSS rule from lessons 16 to 20, in the order they were added. If your own copy behaves differently, compare it line by line with this one. The comments in the stylesheet say which lesson each block came from, so you can jump back to the explanation.

index.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Bench Notes</title>
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <header class="site-header">
    <a class="logo" href="index.html">Bench Notes</a>
    <nav class="main-nav" aria-label="Main">
      <ul class="menu">
        <li><a href="index.html" aria-current="page">Home</a></li>
        <li><a href="guides.html">Guides</a></li>
        <li><a href="tools.html">Tools</a></li>
        <li><a href="contact.html">Contact</a></li>
      </ul>
    </nav>
  </header>
  <main>
    <h1>Welcome to the bench</h1>
    <p>Notes on old hardware, kept in one place.</p>
  </main>
</body>
</html>

style.css

/* Base (lesson 16) */
body {
  margin: 0;
  font-family: system-ui, sans-serif;
  line-height: 1.5;
  color: #1f2328;
}

main {
  padding: 0 24px;
}

/* Header band (lesson 16, text-align from 18, flex from 20) */
.site-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 16px 24px;
  background-color: #1d3b53;
  color: #ffffff;
  border-bottom: 4px solid #f2c14e;
  text-align: center;
}

.site-header a {
  color: inherit;
}

.logo {
  font-size: 1.5rem;
  font-weight: 700;
  letter-spacing: 0.02em;
}

/* Menu (lesson 17, justify-content from 18) */
.menu {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 8px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.menu a {
  display: block;
  padding: 8px 12px;
  border-radius: 4px;
}

/* Link states (lesson 19) */
.logo,
.menu a {
  text-decoration: none;
}

.menu a:hover {
  background-color: rgb(255 255 255 / 0.15);
  text-decoration: underline;
  text-underline-offset: 4px;
}

.menu a[aria-current="page"] {
  text-decoration: underline;
  text-decoration-color: #f2c14e;
  text-decoration-thickness: 3px;
  text-underline-offset: 6px;
}

.logo:focus-visible,
.menu a:focus-visible {
  outline: 2px solid #f2c14e;
  outline-offset: 2px;
}

/* Small screens (lesson 20) */
@media (max-width: 600px) {
  .site-header {
    flex-direction: column;
    gap: 8px;
  }
}

About 85 lines of CSS, and no class in it that the HTML does not use. Rather than go through it rule by rule again, here is what the browser does with it in four situations.

On a wide screen

The body loses its default margin, so the header band runs edge to edge. The header is a flex container with two children, the logo and the nav. justify-content: space-between pushes them to opposite ends, and align-items: center puts them on one center line. The band's own color turns everything inside it white, and color: inherit makes the links follow instead of using the browser's blue.

The nav holds a <ul> that is itself a flex container, so the four list items sit in a row with 8 pixels between them. Each link is a block with padding, which gives it a comfortable click area. Two lines have nothing to do here: text-align: center on the header and justify-content: center on the menu. Neither box has spare room to center anything in.

On a phone

Below 600 pixels the media query switches the header to flex-direction: column. The logo moves on top, the nav goes below, and the existing align-items: center now centers them across the width instead of down the height. If the four links do not fit on one row, flex-wrap: wrap starts a second one, and the justify-content: center from lesson 18 keeps each row centered. Without the viewport meta tag in the head, none of this happens, because the phone would lay the page out as a wide virtual screen.

With a mouse

None of the links are underlined at rest. Pointing at a menu link gives its box a faint white tint and a thin underline, and the rounded corners from lesson 17 show up on the tint. The Home link keeps its thick yellow underline the whole time, hovered or not, because the aria-current rule comes after the hover rule and both weigh the same. The weights are explained in the selectors lesson.

With a keyboard

Pressing Tab moves focus from the logo through the four menu links in source order, and :focus-visible draws a 2 pixel yellow ring around each one as it arrives. Screen reader users get the structure from the HTML: a banner landmark from the <header>, a navigation landmark named "Main", a list of four links, and the current page announced on the Home link.

Where to take it next

A few exercises that build on this code without new theory:

  • Make guides.html, tools.html and contact.html. Copy the header into each, keep the same <link> line, and move aria-current="page" to the matching menu link. One stylesheet now styles four pages, which is the point of the external stylesheets lesson.
  • Keep the header in view while the page scrolls by adding position: sticky; and top: 0; to .site-header. Add enough paragraphs to <main> to test it.
  • Add a <footer> with the same background color. You will type #1d3b53 a second time and the yellow a fourth, which is the moment to look up CSS custom properties, the way to name a value once and reuse it.

A common pattern on phones is a single menu button that shows and hides the links. CSS can style both states, but switching between them on a click takes a little JavaScript, which is where the JavaScript tutorial picks up. The CSS tutorial index lists both projects if you want to revisit a lesson first.

Parts links can earn us a commission. As an Amazon Associate I earn from qualifying purchases.

Try it

Paste index.html into the online HTML editor, delete the <link> line, and put the whole of style.css in a <style> element in its place, since the editor works on a single page. Then change the band color and the yellow accent (it appears three times) to your own scheme, and check the result with the Tab key and a narrow window before calling it done.