004: Links and Navigation
Learning outcomes
By the end of this lesson, you can create useful hyperlinks with a and href, resolve relative paths from the current file, distinguish absolute URLs and fragments, use mailto: and tel: appropriately, and build consistent list-based navigation for a three-page website.
Prerequisites and retrieval
Bring the valid profile article from 003. Explain the roles of a URL's scheme, host, path, query, and fragment. Draw your portfolio folder as a tree; relative links are easiest when file location is visible.
Terminology
- Hyperlink: A link created by an anchor with href that navigates users to another resource. — Source: WHATWG: Links
- Anchor: “The a element … if it has an href attribute, then it represents a hyperlink.” — Source: WHATWG: The a element
- Destination: The URL resolved from a link’s href attribute — where navigation goes. — Source: WHATWG: Links
- Absolute URL: A complete URL including scheme and host, such as https://example.com/about. — Source: WHATWG URL Living Standard: URLs
- Relative URL: A URL without scheme/host that is resolved against a base URL. — Source: WHATWG URL: Relative URL
- Fragment: The part of a URL beginning with # identifying a section within the resource. — Source: WHATWG URL: Fragment
- Root-relative URL: A path starting with “/” resolved from the site origin; formally a path-absolute URL string. — Source: WHATWG URL: Path-absolute
- Navigation: A major group of links for moving through the site, typically wrapped in nav. — Source: WHATWG: The nav element
- Link text: The visible words of a link describing destination or purpose; also its accessible name. — Source: WCAG 2.2: Link Purpose (In Context)
- URL: "A URL is a string that identifies a resource and the mechanism to access it, composed of scheme, host, port, path, query, and fragment." — Source: WHATWG URL Living Standard
- Origin: "An origin is the tuple (scheme, host, port) that identifies the trust boundary for a document." — Source: WHATWG URL: Origin
- Base URL: "The URL against which a relative URL is resolved." — Source: WHATWG URL: Base URL
- Percent-encoding: "Encoding of reserved characters as % followed by two hex digits." — Source: WHATWG URL: Percent-encode
Mental model: directions from where you stand
An absolute URL is a full postal address. A relative URL is a direction from the current document: “the file beside me,” “enter this folder,” or “go up one folder.” The same direction can lead elsewhere when the starting file changes.
Given:
portfolio/ ├─ index.html ├─ about.html ├─ contact.html └─ projects/ └─ weather.html
From index.html, about.html points to its sibling. From projects/weather.html, about.html incorrectly means projects/about.html; use ../about.html to go up first. Forward slashes are URL separators, including on Windows.
Link syntax and purpose
<a href="about.html">About Asha</a>
The content is the link's accessible name. It should identify purpose in context. “Read Asha's biography” is more useful than “click here,” and it still makes sense in a list of links. Do not paste a long URL as text unless knowing the exact URL is itself useful.
Links navigate somewhere. Buttons perform an action on the current page, such as submitting a form. Do not use an anchor without href as a button, and do not use a button to navigate to another document.
Destination forms
<a href="https://developer.mozilla.org/">MDN Web Docs</a>
<a href="projects/weather.html">Weather project</a>
<a href="../index.html">Home</a>
<a href="#contact">Jump to contact details</a>
<a href="about.html#skills">Asha's skills</a>
<a href="mailto:asha@example.com">Email Asha</a>
<a href="tel:+15550123456">Call +1 555 012 3456</a>
mailto: and tel: invoke a configured application; they do not guarantee that email is sent or a call is made. Exposing an email address can attract spam. Display a human-readable phone number while using an international machine-friendly value where appropriate.
Fragments require a unique matching id:
<h2 id="skills">Skills</h2>
IDs must be unique in the document and should be stable, concise, and free of spaces. The browser can scroll and move focus behavior according to the target and user agent. Never create an empty link solely to fake spacing.
Link behavior and relationship attributes
A link can do more than navigate in the current tab, but every extra behavior should have a reason.
<a href="report.pdf" download>Download the report</a>
<a href="https://external.example/guide" target="_blank" rel="noopener">Open external guide in a new tab</a>
downloadsuggests that the target should be downloaded rather than navigated to. Browser and cross-origin restrictions can limit whether the suggestion is honored.target="_blank"opens a new browsing context. Do not use it automatically: unexpected new tabs can disorient users. If you do use it, make the behavior understandable from context.reldescribes the relationship between the current document and the linked resource. Common values includenoopener,noreferrer,nofollow,prev, andnext, but each has a specific purpose.
Modern browsers treat many _blank links as if noopener were present, but writing the relationship explicitly can make security intent clear in maintained code. noreferrer additionally suppresses referrer information and therefore changes analytics and server behavior; do not add it casually.
A URL in href is data. If a destination is generated from untrusted input, validate it before placing it into markup. Avoid javascript: URLs: use real links for navigation and buttons for actions.
Guided example: create three pages
Create index.html, about.html, and contact.html as siblings. Each gets the 002 skeleton, a unique title, one h1, and identical navigation:
<header>
<p>Asha Rao</p>
<nav aria-label="Primary">
<ul>
<li><a href="index.html">Home</a></li>
<li><a href="about.html">About</a></li>
<li><a href="contact.html">Contact</a></li>
</ul>
</nav>
</header>
nav marks major navigation and a list groups the set. aria-label="Primary" gives this region a name; it is useful when a page may have multiple navigation regions. This is a restrained ARIA use, not a replacement for nav. If there is only one obvious navigation region, the label can be omitted.
Use this complete home page:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Home | Asha Rao</title>
</head>
<body>
<header>
<p>Asha Rao</p>
<nav aria-label="Primary">
<ul>
<li><a href="index.html">Home</a></li>
<li><a href="about.html">About</a></li>
<li><a href="contact.html">Contact</a></li>
</ul>
</nav>
</header>
<main>
<h1>Building clear, accessible interfaces — one semantic page at a time</h1>
<p>I am building a portfolio one semantic page at a time.</p>
<p><a href="about.html#skills">Explore my current skills</a></p>
</main>
</body>
</html>
On about.html, add <h2 id="skills">Current skills</h2>. On contact, add visible email and phone links. Test every link from every page, not only from Home. Use the address bar to observe the fragment.
Current-page links may remain links, which lets users return to the page top. A later accessibility enhancement can expose the current item with aria-current="page"; do not add it to every link, and update it separately on each page.
Intermediate example: add a nested project
Create projects/weather.html. Its navigation differs only in path resolution:
<nav aria-label="Primary">
<ul>
<li><a href="../index.html">Home</a></li>
<li><a href="../about.html">About</a></li>
<li><a href="../contact.html">Contact</a></li>
</ul>
</nav>
Link to it from the home page using projects/weather.html. Trace both paths on the folder tree. Avoid /projects/weather.html during local learning: leading slash behavior differs under file: and when a site is hosted at https://host.example/my-portfolio/ rather than the origin root.
For an external project repository:
<a href="https://github.com/example/weather-project">Weather project source code</a>
Opening in a new tab is not a default requirement. It can disorient users and removes their choice. If a real requirement uses target="_blank", clearly indicate the new context. Modern browsers imply noopener for _blank, but explicit policies may still require rel="noopener"; do not add target casually.
Advanced optional extension: meaningful navigation states
On Home only:
<a href="index.html" aria-current="page">Home</a>
The native link still navigates; ARIA communicates current state. On About, move aria-current to About. This is enhancement of correct native HTML. Do not write role="navigation" on nav or role="link" on a; those duplicate native semantics.
Add a footer navigation with an explicit label only if it is genuinely useful:
<nav aria-label="Legal">
<ul>
<li><a href="privacy.html">Privacy</a></li>
</ul>
</nav>
Different labels let landmark users distinguish navigation regions.
Common mistakes and debugging
- Backslashes in URLs: use
/, not\. - Wrong starting point: resolve each relative URL from the document containing the link.
- Filename case mismatch: deployed servers may treat
About.htmlandabout.htmldifferently. - Spaces and unstable names: prefer lowercase names such as
weather-project.html. - Broken fragment: verify exact, unique target
id. href="#"placeholder: it unexpectedly jumps to the top; use a real destination or no unfinished control.- “Click here” repeated: rewrite text around destination or action.
- Confusing link and button: navigation uses
a[href]; actions usebutton. - Testing only locally: verify from the deployed base path as well.
Accessibility, security, and performance
Links must be operable by keyboard and have understandable purpose. Native anchors with href supply focus and activation behavior automatically. Keep navigation order and wording consistent across pages, supporting WCAG Consistent Navigation. Do not remove link underlines or focus indicators in HTML/CSS work without an accessible alternative.
External URLs can disclose the current page through referrer information. Avoid putting secrets in URLs. mailto: can expose addresses publicly; use a server-side contact form later if spam/privacy risk warrants it. Broken links waste time and requests, so include link checking in project review. Fragment navigation is fast and requires no new document request.
Tiered exercises
Level 1: paths
From projects/weather.html, write links to root index.html, sibling projects/gallery.html, and the #results section of the current page.
Level 2: site
Build Home/About/Contact pages with consistent list navigation, distinct titles and headings, an About skills fragment, and meaningful email/phone links.
Level 3: audit
Add one nested project page, mark the current navigation item, then keyboard-test and classify every link as internal, external, fragment, email, or telephone.
Level 1: <a href="../index.html">Home</a>, <a href="gallery.html">Gallery project</a>, and <a href="#results">Project results</a>.
Level 2: use the guided Home document on every page with page-specific title, h1, and body. About includes <h2 id="skills">Current skills</h2>. Contact includes <a href="mailto:asha@example.com">asha@example.com</a> and <a href="tel:+15550123456">+1 555 012 3456</a>. Every navigation URL is correct because files are siblings.
Level 3: nested project navigation uses ../. Exactly one primary navigation link per page has aria-current="page". A keyboard test reaches links in source order with visible browser focus and activates them using Enter. External links remain in the same tab unless a documented requirement says otherwise.
Recap and exit questions
Links connect resources; relative destinations depend on the current file. Link text names purpose, fragments target unique IDs, and list-based nav organizes major destinations.
- From which location is a relative URL resolved?
- Why does
../about.htmlwork from a nested page? - When should you use a button instead of a link?
- What is one privacy concern with
mailto:? - Why should new-tab behavior be exceptional?
Try it with your own example
Relative paths only click once you have been burned by a wrong one, so deliberately break one on purpose before you rely on this skill professionally.
Give Rina's site this structure:
rinas-kitchen/ ├─ index.html ├─ menu.html ├─ order.html └─ menu/ └─ sourdough.html
From menu/sourdough.html, write a link back to the main menu and a link to place an order. Get it wrong first, on purpose:
<a href="menu.html">Back to full menu</a>
Open menu/sourdough.html directly in your browser and click it. It will fail, because from inside menu/, menu.html means menu/menu.html, which does not exist. Now fix it yourself before reading the answer:
<a href="../menu.html">Back to full menu</a>
<a href="../order.html">Order this loaf</a>
You just reproduced, in miniature, the single most common bug beginners ship to a live server: a link that worked while every file sat in one folder, then broke the moment a project grew a subfolder. Deliberately causing it once, on a page nobody depends on, is worth more than reading about it three times.
Further reading: MDN — File paths covers the same ../ mechanics with a different folder example if you want a second worked case.
