MGU Computer Science Series — Web Development: HTML, CSS, and JavaScript
Part V: Web Projects and Components
Headers · Footers · Navigation · Multi-Page Sites
Chapter 26 of 30
26
MGU Computer Science Series  ·  Web Development: HTML, CSS, and JavaScript  ·  Library Textbook Edition

Chapter 26:
Navigation, Headers, Footers,
and Multi-Page Sites

Building consistent, accessible, and connected multi-page websites — shared structure, working navigation, and relative paths that hold together

■ Part V of VII ■

■ 10 Sections  •  Chapter 26 of 30 ■

Builds on Chapters 1–25 — requires working knowledge of HTML structure, CSS layout, and basic JavaScript

Chapter Introduction and Learning Objectives

Until now, most of your work has lived on a single page. You have built good HTML structure, added CSS styling, and made pages interactive with JavaScript. But real websites are not single pages. They are systems of connected pages that share common structure, consistent navigation, and a unified visual identity.

In this chapter, you will move from building individual pages to building small multi-page sites. You will learn how headers, footers, and navigation menus work across an entire site, how to manage relative paths in folders, how to mark the current page in a navigation menu, and how to keep shared sections consistent without a framework. By the end of this chapter, you will be able to plan, build, and link a small multi-page website with shared structure and working navigation.

Opening Question

Open any well-built website and click through five or six pages. The header stays in the same place. The navigation menu lists the same links in the same order. The footer looks identical from page to page. Only the content in the middle changes. How does a site built from separate HTML files manage to feel like one continuous place, rather than five or six unrelated documents? By the end of this chapter, you will know exactly how — and you will have built a five-page site that does it correctly.

10Sections
10Objectives
14Key Terms
30Total Chapters

Learning Objectives

By the end of this chapter, you should be able to:

  1. 1Explain why multi-page websites require consistent shared structure across separate HTML files.
  2. 2Build a site header containing a logo and primary navigation using semantic HTML.
  3. 3Build a site footer containing secondary navigation, contact information, and a copyright statement.
  4. 4Describe three navigation patterns — horizontal, sidebar, and mobile — and identify when each is appropriate.
  5. 5Implement an accessible skip navigation link for keyboard users.
  6. 6Mark the active page in a navigation menu using a CSS class, the aria-current attribute, and a JavaScript-based approach.
  7. 7Build accessible breadcrumb navigation using an ordered list and aria-current.
  8. 8Write correct relative paths for pages located at different folder depths.
  9. 9Describe strategies for managing repeated shared HTML sections across a static multi-page site.
  10. 10Plan a small website's structure with an information architecture diagram and build a complete five-page site with consistent navigation.

Sections at a Glance

Sections 26.1 – 26.3
Shared Structure: Multi-Page Sites, Headers, and Footers
Consistency · Site Headers · Site Footers

From Pages to Sites

When you open a website and click through different pages, something stays the same and something changes. The header at the top stays. The navigation stays. The footer stays. What changes is the main content in the middle. That pattern is not a coincidence. It is an intentional design decision that developers make on purpose.

A multi-page site is a collection of HTML files linked together through navigation. Each file is a separate web page. The pages share a visual identity and structure, but each page has its own content.

Think about the Student Learning Site you have been building throughout this course. It has several planned pages:

Project Pages
index.html        ← Home
about.html        ← About
lessons.html      ← Lessons
resources.html    ← Resources
contact.html      ← Contact

Each of these is a separate HTML file. Each file needs a proper document skeleton, its own <title>, its own <main> content, and links to the shared CSS stylesheet. But each page also needs a header and navigation menu that looks and works the same across every page. That is the central challenge of multi-page development without a framework: keeping things consistent when each page is its own file.

Why Consistency Matters

Imagine navigating a website where the header was in a different place on every page, the navigation links were in a different order, and the footer used different fonts. Even if the design was attractive, the site would feel disorienting and untrustworthy. Users depend on consistent structure to know where they are and where they can go. Designers depend on consistent structure to build a recognizable visual identity.

Consistency also matters for maintenance. If your navigation is copied into ten different HTML files and you add a new page to the site, you need to update ten files. If your CSS is organized carefully and you keep your HTML structure clean, updates become manageable.

What This Chapter Builds

Over the sections that follow, you will build a complete five-page site with a consistent shared header and site logo; a navigation menu that marks the current active page; a consistent footer with contact information and links; properly organized folders and working relative paths; a breadcrumb system for deeper pages; and clean, readable CSS that keeps the site maintainable. Every skill you practice here applies directly to every multi-page website you build in the future.

Headers

A header is the section at the top of every page that identifies the site. It typically contains the site name or logo, the main navigation, and sometimes a tagline or utility links. In HTML, the <header> element marks this content.

The Header Element

You first met <header> in Chapter 6. On a multi-page site, the <header> at the top of the <body> is the site header, not a section header buried inside an article. The site header should appear on every page and contain identical or near-identical content.

Here is a typical site header:

HTML — Site Header
<header class="site-header">
  <div class="header-inner">
    <a href="index.html" class="site-logo">
      <img src="images/logo.png" alt="Student Learning Site">
    </a>
    <nav class="main-nav" aria-label="Main navigation">
      <ul>
        <li><a href="index.html">Home</a></li>
        <li><a href="about.html">About</a></li>
        <li><a href="lessons.html">Lessons</a></li>
        <li><a href="resources.html">Resources</a></li>
        <li><a href="contact.html">Contact</a></li>
      </ul>
    </nav>
  </div>
</header>

Notice several things about this header. The logo is wrapped in an anchor link pointing to index.html. This follows the convention that clicking the site logo returns the user to the home page — it is so common that users expect it.

The <nav> has an aria-label attribute with the value "Main navigation". This label helps screen readers distinguish the main navigation from other navigation elements that might appear elsewhere on the page, such as a footer navigation or a sidebar navigation.

The navigation links are written as an unordered list. This is correct semantic HTML. A list of links is literally a list — do not skip the list markup to save a few lines of code. The list structure communicates meaning.

The paths are relative: index.html, about.html, and so on. This works as long as all pages are in the same folder. Section 26.7 discusses how paths change when pages are in subfolders.

Writing Good Site Logo Alt Text

If your logo is an image, the alt text should give the name of the site. The alt text does not need to say "logo." Screen readers already identify images as images. Write alt="Student Learning Site", not alt="Student Learning Site logo image".

If the logo is text rendered in a custom font using CSS, you can use an <a> element wrapping plain text, and you do not need an image at all. CSS-rendered text is accessible by default and scales well across screen sizes.

HTML — Text-Based Logo
<a href="index.html" class="site-logo">Student Learning Site</a>

Then style the .site-logo class in CSS to use a custom font, a particular size, and whatever visual treatment fits your design. This approach keeps the site name in the HTML where it belongs.

CSS for the Site Header

Here is foundational CSS for a clean, responsive site header:

CSS — Site Header
.site-header {
  background-color: var(--color-primary);
  color: var(--color-white);
  padding: var(--space-md) 0;
}

.header-inner {
  max-width: 1100px;
  margin: 0 auto;
  padding: 0 var(--space-md);
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.site-logo {
  font-size: 1.4rem;
  font-weight: 700;
  color: var(--color-white);
  text-decoration: none;
}

.site-logo:hover {
  color: var(--color-accent);
}

The max-width and margin: 0 auto on .header-inner centers the content and prevents it from stretching too wide on large screens. The display: flex and justify-content: space-between push the logo to the left and the navigation to the right. This is one of the most common header layout patterns on the web.

Footers

The footer sits at the bottom of every page. It closes the page visually and provides information that users look for when they have finished reading the main content. Typical footer contents include a copyright statement and year, contact information or a contact link, secondary navigation (privacy policy, terms of use, accessibility statement), social media links, and a short tagline or mission statement.

In HTML, the <footer> element marks the site footer.

Writing the Site Footer

Here is a typical site footer:

HTML — Site Footer
<footer class="site-footer">
  <div class="footer-inner">
    <div class="footer-info">
      <p class="footer-site-name">Student Learning Site</p>
      <p class="footer-tagline">A resource for MGU web development students.</p>
    </div>
    <nav class="footer-nav" aria-label="Footer navigation">
      <ul>
        <li><a href="index.html">Home</a></li>
        <li><a href="about.html">About</a></li>
        <li><a href="lessons.html">Lessons</a></li>
        <li><a href="resources.html">Resources</a></li>
        <li><a href="contact.html">Contact</a></li>
      </ul>
    </nav>
    <p class="footer-copyright">&copy; 2025 Student Learning Site. All rights reserved.</p>
  </div>
</footer>

The footer has a second <nav> element with aria-label="Footer navigation" to distinguish it from the main site navigation in the header. Both navigation sections cover the same links, but the footer navigation is a convenience for users who reach the bottom of a long page and want to navigate without scrolling back to the top.

The &copy; entity is the HTML copyright symbol ©. The year in a footer copyright should be updated when the site is updated. Some developers write the current year dynamically with JavaScript; others update it manually. Both approaches are reasonable for a beginner site.

CSS for the Site Footer

CSS — Site Footer
.site-footer {
  background-color: var(--color-dark);
  color: var(--color-light);
  padding: var(--space-xl) 0 var(--space-md);
  margin-top: auto;
}

.footer-inner {
  max-width: 1100px;
  margin: 0 auto;
  padding: 0 var(--space-md);
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-lg);
}

.footer-copyright {
  grid-column: 1 / -1;
  border-top: 1px solid var(--color-border);
  padding-top: var(--space-md);
  font-size: 0.875rem;
  color: var(--color-muted);
}

.footer-nav ul {
  list-style: none;
  padding: 0;
  margin: 0;
}

.footer-nav li {
  margin-bottom: var(--space-xs);
}

.footer-nav a {
  color: var(--color-light);
  text-decoration: none;
}

.footer-nav a:hover {
  color: var(--color-accent);
  text-decoration: underline;
}

The footer uses CSS Grid to create a two-column layout. The copyright line spans both columns using grid-column: 1 / -1. The margin-top: auto on .site-footer is a useful trick when the footer is inside a flex-column layout: it pushes the footer to the bottom of the page even when the main content is short.

Making the Footer Stick to the Bottom

On pages with very little content, the footer can appear in the middle of the screen rather than at the bottom, leaving an awkward gap below it. To prevent this, use the following technique on the <body> or the main page wrapper:

CSS — Sticky Footer Pattern
body {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}

main {
  flex: 1;
}
Why This Works

Setting min-height: 100vh means the body is always at least as tall as the viewport. Setting flex: 1 on <main> makes the main content area grow to fill all available space, pushing the footer to the bottom. This is a reliable, widely-used approach, and you will use it again in the full build in Section 26.10.

Active Navigation States

When a user is on the About page, the About link in the navigation should look different from the other links. This is called an active navigation state. It tells the user where they are in the site. Without it, navigation loses an important wayfinding signal.

How Active States Work

The active state is a CSS class, typically named .active or .current, applied to the navigation link that corresponds to the current page. In the HTML for about.html, the navigation would look like this:

HTML — Active Link on about.html
<nav class="main-nav" aria-label="Main navigation">
  <ul>
    <li><a href="index.html">Home</a></li>
    <li><a href="about.html" class="active" aria-current="page">About</a></li>
    <li><a href="lessons.html">Lessons</a></li>
    <li><a href="resources.html">Resources</a></li>
    <li><a href="contact.html">Contact</a></li>
  </ul>
</nav>

Notice two things. First, the .active class is added to the link for the current page. Second, aria-current="page" is added to the same link. The aria-current attribute is an accessibility attribute. It communicates to screen readers that this link represents the page currently being viewed. Use both the visual CSS class and aria-current together.

CSS — Active State Styling
.main-nav a.active,
.main-nav a[aria-current="page"] {
  background-color: var(--color-primary-dark);
  color: var(--color-white);
  border-bottom: 3px solid var(--color-accent);
}

The Limitation of Static Active States

On a static site where each page is a separate HTML file, you must manually add the .active class and aria-current attribute to the correct link on each page. This means the navigation HTML on about.html is slightly different from the navigation HTML on lessons.html. This is one of the real maintenance costs of static multi-page sites without a template system.

There are three approaches to managing this:

Three Approaches
Managing active navigation states across separate files
  • Approach 1Accept the repetition. Each page has its own version of the navigation with the appropriate link marked active. For small sites with few pages, this is the simplest approach. When you add a new page, you update the navigation on all existing pages. Tedious, but reliable.
  • Approach 2Use JavaScript to set the active state automatically. A small JavaScript function can compare the current page's URL to each navigation link's href and add the .active class dynamically. This means all pages share identical navigation HTML, and JavaScript handles the active state at page load.
  • Approach 3Use a build tool or template system. Tools like Eleventy, Jekyll, and Hugo can generate HTML from templates, so you define the navigation once and the tool inserts it into every page with the correct active state. This is the professional approach for larger sites, but it requires setup that goes beyond this course.

For the Student Learning Site, Approach 2 is recommended. It keeps your HTML clean, your navigation consistent, and your JavaScript skills in practice.

JavaScript — Setting Active States Automatically
function setActiveNavLink() {
  const currentPage = window.location.pathname.split('/').pop() || 'index.html';
  const navLinks = document.querySelectorAll('.main-nav a');

  navLinks.forEach(function(link) {
    const linkPage = link.getAttribute('href').split('/').pop();
    if (linkPage === currentPage) {
      link.classList.add('active');
      link.setAttribute('aria-current', 'page');
    }
  });
}

setActiveNavLink();

Place this function in your main.js file. It runs when the page loads, finds the link whose href matches the current filename, and adds the .active class and aria-current attribute automatically. This is a clean, practical solution for a small static site.

Sections 26.7 – 26.10
Holding It Together: Paths, Shared Sections, Site Maps, and the Full Build
Relative Paths · Maintenance Strategies · Information Architecture · Full Project Walkthrough

Relative Paths in Multi-Folder Sites

Chapter 3 introduced relative paths. This section returns to them in the context of a multi-page site with folders, because paths are one of the most common sources of broken links and broken styles in student projects.

The Project Folder Structure

Here is a realistic folder structure for the Student Learning Site with individual lesson pages:

Folder Structure
student-learning-site/
  index.html
  about.html
  lessons.html
  resources.html
  contact.html
  css/
    main.css
  js/
    main.js
  images/
    logo.png
    hero.jpg
    about-photo.jpg
  lessons/
    lesson-01.html
    lesson-02.html
    lesson-03.html
  data/
    resources.json

Pages at the root level (directly inside student-learning-site/) can link to each other with simple filenames: href="about.html". They can link to the CSS file with href="css/main.css". They can link to images with src="images/logo.png".

Pages in subfolders (lessons/lesson-01.html) must account for their position one level deeper. The path ../ means "go up one folder level."

Path Examples for Pages in Subfolders

From lessons/lesson-01.html:

What you are linking toCorrect relative path
Home page../index.html
About page../about.html
Lessons index../lessons.html
CSS file../css/main.css
JavaScript file../js/main.js
Logo image../images/logo.png
Another lessonlesson-02.html (same folder, no ../ needed)

The rule is: count how many folders deep the current file is, then use ../ that many times to get back to the root.

From a file two levels deep (for example, lessons/unit-1/intro.html):

What you are linking toCorrect relative path
Home page../../index.html
CSS file../../css/main.css
Logo image../../images/logo.png

A Practical Technique: Write Paths, Then Check Them

After writing a page in a subfolder, open it in the browser and check four things: does the page title appear in the browser tab (this always works, since <title> needs no path); does the CSS load (check for styled text, colors, and layout — an unstyled page means a broken CSS path); do images appear (broken image icons mean broken image paths); and do navigation links go to the correct pages. Checking these four things immediately after creating a new page will catch path errors early.

Common Path Mistakes

Mistake 1
Using absolute paths starting from the filesystem root
Wrong
<link rel="stylesheet" href="/Users/student/Documents/student-learning-site/css/main.css">
This path works on your computer but breaks on any other computer or server. Always use relative paths in your HTML files.
Mistake 2
Forgetting ../ when inside a subfolder
Wrong for lessons/lesson-01.html
<link rel="stylesheet" href="css/main.css">
Correct for lessons/lesson-01.html
<link rel="stylesheet" href="../css/main.css">
The first path is correct for a root-level page but broken for a page inside the lessons/ folder.
Mistake 3
Using the wrong number of ../
If you are two levels deep and you use only one ../, your path will still be wrong. Count the levels carefully — one ../ per folder level you need to climb.
Mistake 4
Using backslashes
Wrong
<img src="images\logo.png" alt="Logo">
Correct
<img src="images/logo.png" alt="Logo">
HTML paths always use forward slashes, regardless of whether your computer is a Mac, Windows, or Linux machine.

Repeating Shared Sections Carefully

One of the practical challenges of building a static multi-page site is that shared sections — the header, the footer, the skip link — must appear in every HTML file. On a five-page site, this means writing the same header five times. If you decide to add a sixth navigation link, you need to update five files.

This is a real limitation of static HTML sites without a build tool or server-side templating. For the purposes of this course, it is acceptable to work with this limitation. What matters is that you keep your shared sections clean, accurate, and consistent.

Strategies for Managing Repeated Sections

Four Strategies
Managing shared HTML across multiple files
  • Strategy 1Build one page completely first, then duplicate it. Do not start by writing five separate pages from scratch. Write one page fully — correct HTML skeleton, working CSS links, working navigation with all five links, working footer. Then duplicate that file for each other page. Open each duplicate, change the <title>, change the active navigation state, and replace the <main> content. This way, you write the shared structure exactly once and copy it.
  • Strategy 2Keep a "template" file separate from your published pages. Create a file called _template.html (the underscore signals it is not a public page). Keep it in your project root. Whenever you need to add a new page, copy this template. Whenever you need to update shared sections, update the template and apply the same update to all active pages.
  • Strategy 3Use JavaScript includes (an introductory technique). It is possible to write JavaScript that loads the header and footer HTML from separate files and inserts them into the page. This is sometimes called a "JavaScript include." It keeps shared content in one file, but it has trade-offs: the content loads after the page's initial render, which can cause a flash of unstyled content, and it is more complex to implement correctly. It is a pattern worth knowing about, but for this course, copying clean HTML is more reliable.
  • Strategy 4Note what frameworks solve. One reason developers use frameworks like React, Vue, or Astro, and template engines like Eleventy, Jekyll, and Hugo, is precisely this problem. These tools let you define shared components or layouts once and reuse them across every page automatically. When you take a later course in front-end development or full-stack development, you will encounter this solution directly. For now, understanding the problem that frameworks solve is itself valuable knowledge.

Keeping Shared Sections Identical

When you copy shared HTML across pages, it is easy to accidentally introduce small differences. A misspelled class name, a missing list item, or a different image path in one file can cause confusing bugs. Before publishing a multi-page site, do a final review.

Final Review Checklist

Open each page in the browser. Visually compare the header and footer across pages. Click every navigation link from every page to confirm it works. Check the browser tab title on each page to confirm it is page-specific. This review takes only a few minutes and catches the most common consistency errors.

Site Maps and Page Relationships

A site map is a document or diagram that shows all the pages on a site and how they relate to each other. Site maps exist at two levels: the information architecture level (planning) and the technical level (implementation).

Information Architecture Site Maps

Before you write a single line of code for a multi-page site, it is worth sketching the site's structure. Which pages exist? Which pages link to which? What is the hierarchy?

For the Student Learning Site, the information architecture is flat: all main pages are at the same level with no deep hierarchy. But if the site grew, it might look like this:

Information Architecture Diagram
Home
├── About
├── Lessons
│   ├── Lesson 01: Intro to HTML
│   ├── Lesson 02: CSS Basics
│   └── Lesson 03: The Box Model
├── Resources
└── Contact

This is called a tree structure or hierarchy. The home page is the root. The main section pages (About, Lessons, Resources, Contact) are one level down. Individual lesson pages are two levels down.

Understanding the hierarchy helps you name your folders consistently (lessons/), write correct relative paths (root pages use ../ to reach subfolders; subpages use ../../ to reach the root), design navigation that reflects the hierarchy, and write breadcrumbs that match the hierarchy.

Technical Site Maps (XML Sitemaps)

When a site is published on a web server, it can include a sitemap.xml file. This file lists every page on the site in a format that search engines can read. Search engines use the sitemap to discover and index all pages, even pages that are not directly linked from the home page.

Two Audiences for Two Kinds of Site Maps

Writing XML sitemaps is beyond the scope of this chapter — it is introduced in Chapter 30 as part of the publishing process. What matters here is understanding that sitemaps serve two different audiences: the visual site map is for you and your team, and the XML sitemap is for search engines.

Planning Links Thoughtfully

A site where every page links to every other page is easy to navigate but can feel overwhelming if the site grows large. A site where some pages are hard to find because they are only linked from one obscure location loses users. Good information architecture means every page is reachable from the main navigation, from the footer, or through a clear path of links; related pages link to each other within their content; the home page links to the main sections; section pages link to their subsection pages; and users can always find a path back to the home page.

Building a Small Multi-Page Site

This section walks through building the Student Learning Site as a complete five-page static site. Work through each step in sequence. By the end, you will have a working multi-page site with shared navigation, active states, a footer, and correct relative paths.

Build Walkthrough
Eight steps to a complete five-page site
  • Step 1Create the folder structure shown below. Leave all the HTML files empty for now. Create the folders and files first.
  • Step 2Write the CSS variables and base styles in css/main.css, including colors, spacing tokens, and the flex-column body for the sticky footer pattern.
  • Step 3Write the site header CSS — the skip link, the sticky header, and the main navigation, including the active-state rules.
  • Step 4Write the site footer CSS — the responsive two-column grid, the footer navigation, and the copyright line.
  • Step 5Write the JavaScript for active navigation states in js/main.js, using the DOMContentLoaded event.
  • Step 6Write the complete home page, index.html, with the skip link, header, navigation, main content, footer, and script tag all in place.
  • Step 7Duplicate index.html to create about.html, lessons.html, resources.html, and contact.html. Update each page's title, description, and main content.
  • Step 8Test the complete site: click through every page, confirm the active link updates, confirm the footer stays at the bottom, and check the console for errors.

Step 1: Create the Folder Structure

Folder Structure
student-learning-site/
  index.html
  about.html
  lessons.html
  resources.html
  contact.html
  css/
    main.css
  js/
    main.js
  images/
    (place your image files here)
  data/
    resources.json

Step 2: Write the CSS Variables and Base Styles

Open css/main.css. Define your CSS custom properties at the top, then write base styles for the body and typography.

CSS — Variables and Base Styles
/* ===================================
   CSS Variables
   =================================== */

:root {
  /* Colors */
  --color-primary: #1a4e8a;
  --color-primary-dark: #133d6e;
  --color-accent: #f5a623;
  --color-white: #ffffff;
  --color-dark: #1c1c1e;
  --color-light: #f5f5f7;
  --color-text: #2c2c2e;
  --color-muted: #6e6e73;
  --color-border: rgba(255, 255, 255, 0.15);
  --color-hover-bg: #f0f4fa;

  /* Spacing */
  --space-xs: 0.25rem;
  --space-sm: 0.5rem;
  --space-md: 1rem;
  --space-lg: 1.5rem;
  --space-xl: 2.5rem;
  --space-xxl: 4rem;
}

/* ===================================
   Base Styles
   =================================== */

*, *::before, *::after {
  box-sizing: border-box;
}

body {
  font-family: Georgia, 'Times New Roman', serif;
  font-size: 1rem;
  line-height: 1.7;
  color: var(--color-text);
  background-color: var(--color-white);
  margin: 0;
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}

img {
  max-width: 100%;
  height: auto;
  display: block;
}

a {
  color: var(--color-primary);
}

a:hover {
  color: var(--color-primary-dark);
}

main {
  flex: 1;
}

.page-container {
  max-width: 1100px;
  margin: 0 auto;
  padding: var(--space-xl) var(--space-md);
}

Step 3: Write the Site Header CSS

CSS — Skip Link and Site Header
/* ===================================
   Skip Link
   =================================== */

.skip-link {
  position: absolute;
  top: -100%;
  left: var(--space-md);
  background-color: var(--color-primary);
  color: var(--color-white);
  padding: var(--space-sm) var(--space-md);
  border-radius: 0 0 4px 4px;
  font-weight: 700;
  text-decoration: none;
  z-index: 1000;
  transition: top 0.2s;
}

.skip-link:focus {
  top: 0;
}

/* ===================================
   Site Header
   =================================== */

.site-header {
  background-color: var(--color-primary);
  color: var(--color-white);
  padding: var(--space-md) 0;
  position: sticky;
  top: 0;
  z-index: 100;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
}

.header-inner {
  max-width: 1100px;
  margin: 0 auto;
  padding: 0 var(--space-md);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-md);
}

.site-logo {
  font-size: 1.25rem;
  font-weight: 700;
  color: var(--color-white);
  text-decoration: none;
  white-space: nowrap;
}

.site-logo:hover {
  color: var(--color-accent);
}

/* ===================================
   Main Navigation
   =================================== */

.main-nav ul {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  gap: var(--space-xs);
}

.main-nav a {
  display: block;
  color: var(--color-white);
  text-decoration: none;
  font-size: 0.9375rem;
  padding: var(--space-xs) var(--space-sm);
  border-radius: 4px;
  transition: background-color 0.2s;
}

.main-nav a:hover {
  background-color: var(--color-primary-dark);
  color: var(--color-white);
}

.main-nav a.active,
.main-nav a[aria-current="page"] {
  background-color: var(--color-primary-dark);
  color: var(--color-accent);
  font-weight: 600;
}

Step 4: Write the Site Footer CSS

CSS — Site Footer
/* ===================================
   Site Footer
   =================================== */

.site-footer {
  background-color: var(--color-dark);
  color: var(--color-light);
  padding: var(--space-xl) 0 var(--space-lg);
}

.footer-inner {
  max-width: 1100px;
  margin: 0 auto;
  padding: 0 var(--space-md);
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-lg);
}

@media (max-width: 600px) {
  .footer-inner {
    grid-template-columns: 1fr;
  }
}

.footer-site-name {
  font-size: 1.1rem;
  font-weight: 700;
  margin: 0 0 var(--space-xs);
}

.footer-tagline {
  font-size: 0.875rem;
  color: var(--color-muted);
  margin: 0;
}

.footer-nav ul {
  list-style: none;
  padding: 0;
  margin: 0;
}

.footer-nav li {
  margin-bottom: var(--space-xs);
}

.footer-nav a {
  color: var(--color-light);
  text-decoration: none;
  font-size: 0.9375rem;
}

.footer-nav a:hover {
  color: var(--color-accent);
  text-decoration: underline;
}

.footer-copyright {
  grid-column: 1 / -1;
  border-top: 1px solid rgba(255, 255, 255, 0.1);
  padding-top: var(--space-md);
  margin-top: var(--space-md);
  font-size: 0.875rem;
  color: var(--color-muted);
}

Step 5: Write the JavaScript for Active Navigation States

Open js/main.js and add the following function:

JavaScript — main.js
/* ===================================
   Active Navigation State
   =================================== */

function setActiveNavLink() {
  // Get the current page filename
  // For the home page (index.html or just /), fall back to 'index.html'
  const pathParts = window.location.pathname.split('/');
  const currentPage = pathParts[pathParts.length - 1] || 'index.html';

  // Select all links in the main navigation
  const navLinks = document.querySelectorAll('.main-nav a');

  navLinks.forEach(function(link) {
    // Get the filename from the link's href
    const hrefParts = link.getAttribute('href').split('/');
    const linkPage = hrefParts[hrefParts.length - 1];

    if (linkPage === currentPage) {
      link.classList.add('active');
      link.setAttribute('aria-current', 'page');
    }
  });
}

// Run when the page loads
document.addEventListener('DOMContentLoaded', setActiveNavLink);
Tracing the Function

The function splits the current URL's pathname to get the filename of the current page. It then compares that filename to each navigation link's href. When it finds a match, it adds the .active class and the aria-current attribute. The DOMContentLoaded event ensures the function runs after the HTML has fully loaded but before images and stylesheets finish loading, so the active state is applied as soon as the navigation is available.

Step 6: Write the Home Page

Open index.html and write the complete page. Notice that the navigation HTML is identical on every page — the active state is set by JavaScript, not by hand:

HTML — index.html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta name="description" content="A learning resource for MGU web development students.">
  <title>Home — Student Learning Site</title>
  <link rel="stylesheet" href="css/main.css">
</head>
<body>

  <a href="#main-content" class="skip-link">Skip to main content</a>

  <header class="site-header">
    <div class="header-inner">
      <a href="index.html" class="site-logo">Student Learning Site</a>
      <nav class="main-nav" aria-label="Main navigation">
        <ul>
          <li><a href="index.html">Home</a></li>
          <li><a href="about.html">About</a></li>
          <li><a href="lessons.html">Lessons</a></li>
          <li><a href="resources.html">Resources</a></li>
          <li><a href="contact.html">Contact</a></li>
        </ul>
      </nav>
    </div>
  </header>

  <main id="main-content">
    <div class="page-container">
      <h1>Welcome to the Student Learning Site</h1>
      <p>This site is a resource for students learning web development. Explore the lessons, browse the resources, and use the contact page to get in touch.</p>
      <p>Start with the <a href="lessons.html">Lessons page</a> or browse the <a href="resources.html">Resources</a>.</p>
    </div>
  </main>

  <footer class="site-footer">
    <div class="footer-inner">
      <div class="footer-info">
        <p class="footer-site-name">Student Learning Site</p>
        <p class="footer-tagline">A resource for MGU web development students.</p>
      </div>
      <nav class="footer-nav" aria-label="Footer navigation">
        <ul>
          <li><a href="index.html">Home</a></li>
          <li><a href="about.html">About</a></li>
          <li><a href="lessons.html">Lessons</a></li>
          <li><a href="resources.html">Resources</a></li>
          <li><a href="contact.html">Contact</a></li>
        </ul>
      </nav>
      <p class="footer-copyright">&copy; 2025 Student Learning Site. All rights reserved.</p>
    </div>
  </footer>

  <script src="js/main.js"></script>
</body>
</html>

Step 7: Duplicate to the Other Pages

Copy index.html to about.html, lessons.html, resources.html, and contact.html. Then in each copy: update the <title> element to match the page name — for example, <title>About — Student Learning Site</title>; update the <meta name="description"> to a description appropriate for that page; replace the <main> content with the actual content for that page; and verify that all CSS, JavaScript, and image paths are correct for a root-level page.

No Manual Navigation Edits Needed

Because JavaScript handles the active navigation state, you do not need to change the navigation HTML on any page. Every page shares exactly the same header and footer markup.

Step 8: Test the Complete Site

Open index.html in the browser and verify the header appears on every page; the active navigation link is highlighted on each page (check by clicking through all five pages); every navigation link goes to the correct page; the footer appears on every page; the footer navigation links work; no CSS or JavaScript errors appear in the browser console; and on short-content pages, the footer sits at the bottom of the viewport.

Chapter Summary

Key Terms

active navigation state
A visual style applied to the navigation link for the current page, helping users understand where they are on the site.
aria-current="page"
An ARIA attribute added to the navigation link for the currently viewed page, communicating the active page to assistive technologies.
aria-label
An attribute that provides a text label for an element, used to distinguish multiple <nav> elements on the same page.
breadcrumb
A secondary navigation element that displays the user's location within the site's hierarchy as a series of links leading back to the home page.
DOMContentLoaded
A browser event that fires when the HTML document has fully loaded and the DOM is ready to be manipulated, before images and stylesheets finish loading.
footer
The <footer> element at the bottom of every page, containing contact information, secondary navigation, copyright, and supporting links.
header
The <header> element at the top of every page, containing the site logo, primary navigation, and page identification.
information architecture
The structure and organization of a website's content, defining how pages relate to each other and how users navigate between them.
multi-page site
A website consisting of multiple separate HTML files linked together through navigation.
relative path
A file path that describes a location relative to the current file's location, using ../ to navigate up folder levels.
site map
A diagram or document showing all pages on a site and their relationships. In technical web contexts, also an XML file listing site pages for search engines.
skip navigation link
A hidden link at the top of the page that lets keyboard users jump directly to the main content, bypassing the header and navigation.
sticky positioning
A CSS positioning value (position: sticky) that keeps an element fixed in view as the user scrolls until it reaches the edge of its containing element. Useful for headers.
XML sitemap
A file named sitemap.xml at the root of a published website that lists all pages for search engines to discover and index.
PracticeCode Reading

Read the following navigation markup carefully, then answer the questions below.

HTML — Brightfield Academy Header
<a href="#main-content" class="skip-link">Skip to main content</a>

<header class="site-header">
  <div class="header-inner">
    <a href="index.html" class="site-logo">Brightfield Academy</a>
    <nav class="main-nav" aria-label="Main navigation">
      <ul>
        <li><a href="index.html">Home</a></li>
        <li><a href="courses.html">Courses</a></li>
        <li><a href="instructors.html">Instructors</a></li>
        <li><a href="blog.html">Blog</a></li>
        <li><a href="contact.html">Contact</a></li>
      </ul>
    </nav>
  </div>
</header>
  1. What is the purpose of aria-label="Main navigation" on the <nav> element? When would this label be especially important?
  2. The skip link has href="#main-content". For the skip link to work, what must exist elsewhere in the HTML? Write the opening tag of the element it would need to target.
  3. A user visits courses.html. The JavaScript active-state function runs. Which <a> element will receive the .active class and aria-current="page" attribute? Write what that element looks like after JavaScript modifies it.
  4. The site logo is a text link (an <a> with text content), not an image. What advantage does this approach have over using an <img> element for the logo?
  5. If the site later adds a courses/ subfolder containing courses/intro-html.html, and this page needs to link to the same CSS file at css/main.css, what relative path should it use for the stylesheet link?
PracticeCode Tracing

Trace the following JavaScript function step by step. The current page being viewed is resources.html.

JavaScript
function setActiveNavLink() {
  const pathParts = window.location.pathname.split('/');
  const currentPage = pathParts[pathParts.length - 1] || 'index.html';

  const navLinks = document.querySelectorAll('.main-nav a');

  navLinks.forEach(function(link) {
    const hrefParts = link.getAttribute('href').split('/');
    const linkPage = hrefParts[hrefParts.length - 1];

    if (linkPage === currentPage) {
      link.classList.add('active');
      link.setAttribute('aria-current', 'page');
    }
  });
}

The navigation contains these links in order: <a href="index.html">Home</a>, <a href="about.html">About</a>, <a href="lessons.html">Lessons</a>, <a href="resources.html">Resources</a>, and <a href="contact.html">Contact</a>. Assume window.location.pathname returns /student-learning-site/resources.html.

  1. What does window.location.pathname.split('/') produce? Write the resulting array.
  2. What does pathParts[pathParts.length - 1] evaluate to?
  3. What is the value of currentPage?
  4. For each of the five navigation links, write the value of linkPage and whether the if condition is true or false.
  5. After the function completes, which link has .active added to its class list and aria-current="page" added as an attribute?
PracticePredict the Result

Look at the following CSS and HTML. Predict what the breadcrumb trail will look like in the browser.

CSS
.breadcrumbs ol {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-wrap: wrap;
}

.breadcrumbs li:not(:last-child)::after {
  content: '›';
  margin: 0 0.5rem;
  color: #888;
}

.breadcrumbs a {
  color: #1a4e8a;
  text-decoration: none;
}

.breadcrumbs [aria-current="page"] {
  color: #2c2c2e;
  font-weight: 500;
}
HTML
<nav class="breadcrumbs" aria-label="Breadcrumb">
  <ol>
    <li><a href="../../index.html">Home</a></li>
    <li><a href="../lessons.html">Lessons</a></li>
    <li aria-current="page">Lesson 4: Flexbox</li>
  </ol>
</nav>

Describe: Which items are links and which are plain text? What color are the links? What color is the current page item? What character appears between each item, and what color is it?

PracticeDebugging and Error Analysis

Each of the following samples contains one or more errors. Identify the error and explain how to fix it.

Sample A

A page located at lessons/lesson-02.html links to the stylesheet like this:

HTML
<link rel="stylesheet" href="css/main.css">

The page loads with no styles applied. What is the problem, and how do you fix it?

Sample B

A developer adds two <nav> elements to the page but gives both the same aria-label:

HTML
<nav aria-label="Main navigation">
  <!-- main nav links -->
</nav>

<!-- later in the footer -->

<nav aria-label="Main navigation">
  <!-- footer nav links -->
</nav>

Why is this a problem for accessibility, and what should the developer change?

Sample C

A developer writes the following skip link, but pressing Tab does not reveal it, and pressing Enter does not move focus to the main content.

HTML
<a href="main-content" class="skip-link">Skip to main content</a>

<!-- ... later ... -->

<main class="main-content">

There are two errors. Identify both and explain the corrections.

Sample D

A developer wants the footer to stay at the bottom of the viewport even on short pages. They write:

CSS
body {
  min-height: 100vh;
}

.site-footer {
  position: absolute;
  bottom: 0;
}

The footer does sit at the bottom of the viewport, but now it overlaps the main content on short pages. What is the correct approach, and why does position: absolute cause this problem?

PracticeShort Build Tasks
  1. Site Header. Write the complete HTML for a site header for a fictional site called "Coastal Science Museum." The header should include a text-based logo linking to index.html; a skip link pointing to #main-content; and a <nav> with five links: Home, Exhibits, Events, Education, and Visit. Use appropriate semantic HTML and ARIA attributes.
  2. Navigation CSS. Write the complete CSS for a horizontal main navigation that meets these requirements: links are white on a dark blue background (#1a4e8a); on hover, links show a darker blue background (#133d6e); the active link is visually distinct (your choice of style); links have adequate padding for a comfortable click target (at minimum 0.5rem top/bottom and 0.75rem left/right); no bullet points or underlines on the links.
  3. Path Practice. A site has three levels of pages: index.html at the root, section pages like exhibits/index.html one level deep, and detail pages like exhibits/dinosaurs/triceratops.html two levels deep. Write the relative href paths, all written from inside exhibits/dinosaurs/triceratops.html, for: a link to the home page; a link to the exhibits section index; a link to the CSS file at css/main.css; a link to a nearby page at exhibits/dinosaurs/brachiosaurus.html; and a link to a page at events/upcoming.html.
  4. Active State Script. Write the JavaScript function that sets the active navigation state, using the DOMContentLoaded event. Add a comment to each meaningful line explaining what it does.
  5. Breadcrumb Trail. Write a complete, accessible breadcrumb navigation for a page called "Triceratops" that is two levels deep on the Coastal Science Museum site. The hierarchy is: Home → Exhibits → Triceratops. Use the correct HTML element for the list, mark the current page with aria-current, use appropriate paths (assume two levels deep), and give the <nav> an appropriate aria-label.
Mini-ProjectFive-Page Website

Build a complete five-page static website using everything covered in this chapter and the chapters before it. You may build the Student Learning Site as specified, or choose an alternative theme: a school club site (Drama Club, Science Club, Photography Club), a small community organization site, a personal portfolio site, or a hobby or interest site on a topic of your choice.

Required pages: Home, About, a content section page (Lessons, Projects, Gallery, or equivalent), a Resources or Links page, and a Contact page.

Required Features

  • A consistent <header> on every page with a text-based or image-based logo and main navigation.
  • A skip navigation link on every page.
  • A consistent <footer> on every page with copyright, a site description, and footer navigation links.
  • Working relative paths for CSS and JavaScript on all pages.
  • An external CSS file (css/main.css) with CSS custom properties used throughout.
  • An external JavaScript file (js/main.js) with the active navigation state function.
  • Correct aria-label attributes on both the main navigation and the footer navigation.
  • A body flex layout that keeps the footer at the bottom of short pages.
  • A sticky header using position: sticky.
  • At least one page with meaningful main content (not placeholder text).
  • At least two images with correct alt text.

Accessibility Requirements

  • Skip link that becomes visible on keyboard focus.
  • All images have descriptive alt text.
  • All navigation links have meaningful text.
  • Heading order is correct on every page (one <h1> per page, headings in descending order).

Testing Checklist

  • Open every page in the browser and verify the header and footer appear consistently.
  • Click every navigation link from every page and confirm it loads the correct page.
  • Confirm the active navigation state highlights the correct link on each page.
  • Open the browser console on every page and confirm no errors appear.
  • Tab through the page on at least one page and confirm the skip link appears and functions.
  • Resize the browser window and confirm the layout remains usable at narrow widths.

Accessibility Check

Review a partner's five-page site or review your own site using the following questions. Mark each item as Met, Partially Met, or Not Met, and note specific issues where you find them.

  1. 1Does every page have a skip navigation link that becomes visible on keyboard focus and sends focus to <main>?
  2. 2Is aria-label present on both the main navigation and the footer navigation, with different labels on each?
  3. 3Are navigation links marked with aria-current="page" for the current page?
  4. 4Does every page have exactly one <h1> that identifies the page's main topic?
  5. 5Are headings in correct descending order (<h1> → <h2> → <h3>) with no levels skipped?
  6. 6Do all images have alt attributes? Are the alt texts descriptive and meaningful?
  7. 7Can you navigate through the entire site using only the keyboard? Do focus indicators remain visible?
  8. 8Does the site logo link back to the home page?
  9. 9Are footer navigation links meaningful? (Avoid "click here" or "link".)
  10. 10Does the footer appear at the bottom of short-content pages rather than floating in the middle of the viewport?
ReviewMixed Review

These questions review skills from earlier chapters alongside the new material from this chapter.

  1. (Chapter 3) A file at lessons/unit-2/lesson-05.html needs to display an image stored at images/diagrams/flexbox.png from the root of the project. Write the correct <img> tag with the path, an appropriate alt attribute, and a width of 700 and height of 400.
  2. (Chapter 6) The home page of a site has this heading structure: one <h1>, followed by three <h3> elements. What is wrong with this structure and how do you fix it?
  3. (Chapter 12) A developer writes .main-nav a.active in CSS. Explain how CSS reads this selector. Which elements will it match and which will it not match?
  4. (Chapter 15) Explain why display: flex and justify-content: space-between are used on .header-inner in this chapter. What does each declaration do, and what visual result do they produce together?
  5. (Chapter 17) The site header has position: sticky; top: 0. Explain what position: sticky does differently from position: fixed. Why might you prefer sticky over fixed for a site header?
  6. (Chapter 22) The setActiveNavLink() function uses document.querySelectorAll('.main-nav a'). What does querySelectorAll return? How does it differ from querySelector?
  7. (Chapter 23) The setActiveNavLink() function uses navLinks.forEach(function(link) { ... }). Explain what forEach does and why it is appropriate here instead of a regular for loop.
  8. (Chapter 26 — this chapter) A developer builds a five-page static site and decides to manage active navigation states manually (adding .active and aria-current by hand in the HTML on each page). Describe the maintenance problem this creates. What happens when they add a sixth page to the site?
Chapter 26 Checklist
Use this to confirm your understanding before moving to Chapter 27
Concepts
  • I can explain why multi-page websites need consistent shared structure across separate HTML files.
  • I can describe what a site header and a site footer typically contain.
  • I can name three navigation patterns and explain when each is used.
  • I can explain what a skip navigation link does and why it matters for accessibility.
  • I can explain the difference between marking active states by hand and marking them with JavaScript.
  • I can explain when breadcrumbs are useful and when they are not.
  • I can explain how to count folder depth and write the correct number of ../ segments.
  • I can describe at least two strategies for managing repeated shared HTML sections.
  • I can explain the difference between an information architecture diagram and an XML sitemap.
Applications
  • I can build a complete site header with a logo, skip link, and accessible navigation.
  • I can build a complete site footer with footer navigation and a copyright line.
  • I can write a JavaScript function that automatically marks the active navigation link.
  • I can write correct relative paths for pages at any folder depth.
  • I can build a complete, consistent, accessible five-page static website.
Study Habits
  • I check CSS, JavaScript, and image paths immediately after creating any new page.
  • I test every navigation link by clicking through the entire site, not just the page I just edited.
  • I review shared sections across all pages for consistency before considering a site finished.
Preview — Chapter 27
Cards, Galleries, Accordions, Tabs, and UI Patterns

Chapter 27 introduces common user interface patterns: card grids, image galleries, accordions, tabbed content, and show/hide behaviors. These patterns appear on nearly every real website, and building them requires combining everything you have learned about HTML structure, CSS styling, and JavaScript interaction.

You will learn how to toggle CSS classes with JavaScript to show and hide content, how to build an accordion where only one item is open at a time, how to build a tabbed interface that switches between sections without a page reload, and how keyboard interaction works for these components. Accessibility returns to the center of attention: interactive patterns that work with a mouse but not a keyboard exclude many users, so Chapter 27 introduces the fundamental ARIA roles and keyboard behaviors that make interactive patterns inclusive.

The mini-project in Chapter 27 will be a FAQ accordion or a tabbed lesson guide — both components you can add directly to your Student Learning Site.

MGU Library Connection
  • Web Development: HTML, CSS, and JavaScript — Appendix A: Web Project Setup Reference
  • Web Development: HTML, CSS, and JavaScript — Appendix C: Semantic HTML and Accessibility Reference
  • Web Development: HTML, CSS, and JavaScript — Appendix J: Developer Tools and Debugging Reference
  • Companion resource: Link and Path Guide
  • Companion resource: Browser Developer Tools Guide
  • Companion resource: Accessibility Checklist
  • Next chapter: Cards, Galleries, Accordions, Tabs, and UI Patterns (builds directly on this chapter's navigation foundation)
  • MGU Digital Literacy — background reading on information architecture and site planning