HTML5 Mastery: The Complete Web Foundation
HomeInsightsCoursesHTMLPage Anchors & Bookmarks
Deep Linking & UX

The Art of Page Anchors & Bookmarks

Transform your long-form content into an interactive roadmap. Master URL fragments, the :target pseudo-class, and advanced scroll-orchestration to create professional-grade Single Page Navigation.

Senior Engineering Insight: In modern web applications, anchors are the backbone of "Deep Linking." They allow users to share specific states or sections of a page, significantly increasing user retention and conversion rates by reducing the "search friction" within your UI.

1. The Anatomy of a URL Fragment

A page anchor relies on the URL Fragment (the part of a URL starting with the # character). Unlike query parameters (?id=123), fragments are handled entirely on theclient-side. The browser does not send the fragment to the server; it uses it to locate an element with a matching ID in the DOM.

Identifier Match

The browser searches for any element where id="fragment". If found, it calculates the element's coordinate and scrolls the viewport.

The Null Fragment (#)

A bare # is a special case that always scrolls the user back to the top of the <html> element.

Technical Note: Historically, developers used<a name="target"> for anchors. This isobsolete. Modern HTML5 uses the idattribute on any element as a valid anchor target.

2. The Strategic Table of Contents (TOC)

A Table of Contents is the most common implementation of anchors. Beyond mere navigation, it provides users with a visual mental map of your content's hierarchy.

FeatureStatic TOCSticky/Floating TOC
VisibilityOnly at the topAlways visible while scrolling
UX ValueGood for initial overviewExcellent for switching sections mid-read
ImplementationStandard List of LinksCSS position: sticky

Senior UX Tip: For extremely long technical articles, a sticky sidebar TOC with active state tracking(using Intersection Observer) is the gold standard. It tells the user exactly where they are in the "story" of your documentation.

Basic Anchor Links

Create anchor links using the hash symbol (#) followed by an element's ID:

Simple Anchor Link Example
HTML
<!DOCTYPE html>
<html>
<head>
    <title>Anchor Links Demo</title>
</head>
<body>
    <!-- Link that jumps to a section --&gt;
    <nav>
        <a href="#introduction">Introduction</a>
        <a href="#features">Features</a>
        <a href="#pricing">Pricing</a>
        <a href="#contact">Contact</a>
    </nav>

    <!-- Target sections with matching IDs --&gt;
    <section id="introduction">
        <h2>Introduction</h2>
        <p>Content here...</p>
    </section>

    <section id="features">
        <h2>Features</h2>
        <p>Content here...</p>
    </section>

    <section id="pricing">
        <h2>Pricing</h2>
        <p>Content here...</p>
    </section>

    <section id="contact">
        <h2>Contact</h2>
        <p>Content here...</p>
    </section>
</body>
</html>

How It Works:

  1. Add unique id attribute to target element
  2. Create link with href="#id-name"
  3. Clicking the link scrolls to that element
  4. URL updates to include the fragment (e.g., page.html#features)

Table of Contents Pattern

A common pattern for long articles and documentation:

Table of Contents
HTML
<article>
    <header>
        <h1>Complete HTML Guide</h1>
        
        <!-- Table of Contents --&gt;
        <nav aria-label="Table of contents">
            <h2>Table of Contents</h2>
            <ol>
                <li><a href="#what-is-html">What is HTML?</a></li>
                <li><a href="#getting-started">Getting Started</a></li>
                <li><a href="#basic-tags">Basic Tags</a>
                    <ol>
                        <li><a href="#headings">Headings</a></li>
                        <li><a href="#paragraphs">Paragraphs</a></li>
                        <li><a href="#links">Links</a></li>
                    </ol>
                </li>
                <li><a href="#best-practices">Best Practices</a></li>
            </ol>
        </nav>
    </header>

    <main>
        <section id="what-is-html">
            <h2>What is HTML?</h2>
            <p>HTML stands for HyperText Markup Language...</p>
        </section>

        <section id="getting-started">
            <h2>Getting Started</h2>
            <p>To begin with HTML...</p>
        </section>

        <section id="basic-tags">
            <h2>Basic Tags</h2>
            
            <h3 id="headings">Headings</h3>
            <p>HTML has six heading levels...</p>
            
            <h3 id="paragraphs">Paragraphs</h3>
            <p>Paragraphs are created with...</p>
            
            <h3 id="links">Links</h3>
            <p>Links connect pages together...</p>
        </section>

        <section id="best-practices">
            <h2>Best Practices</h2>
            <p>Follow these guidelines...</p>
        </section>
    </main>
</article>

"Back to Top" Button

Let users quickly return to the page top:

Back to Top Implementation
HTML
<body>
    <!-- Add ID to top element --&gt;
    <header id="top">
        <h1>Page Title</h1>
        <nav>...</nav>
    </header>

    <main>
        <!-- Long content --&gt;
        <p>Lots of content...</p>
    </main>

    <footer>
        <!-- Back to top link --&gt;
        <a href="#top" class="back-to-top">⬆ Back to Top</a>
    </footer>
</body>

<style>
.back-to-top {
    display: inline-block;
    padding: 0.75rem 1.5rem;
    background-color: #007bff;
    color: white;
    text-decoration: none;
    border-radius: 5px;
    transition: background-color 0.3s;
}

.back-to-top:hover {
    background-color: #0056b3;
}

/* Fixed position button (alternative) */
.back-to-top.fixed {
    position: fixed;
    bottom: 20px;
    right: 20px;
    box-shadow: 0 4px 8px rgba(0,0,0,0.2);
}
</style>
💡
Pro Tip: You can link to href="#" or href="#top"to scroll to the top, even without an ID. However, using an explicit ID is more semantic.

Smooth Scrolling

Add smooth animated scrolling for better user experience:

CSS-Only Smooth Scrolling

CSS
/* Apply to entire page */
html {
    scroll-behavior: smooth;
}

/* Or apply to specific container */
.scrollable-container {
    scroll-behavior: smooth;
}
⚠️ Accessibility Consideration: Some users with vestibular disorders prefer reduced motion. Respect their preferences:
Respect User Preferences
CSS
/* Only apply smooth scrolling if user hasn't requested reduced motion */
@media (prefers-reduced-motion: no-preference) {
    html {
        scroll-behavior: smooth;
    }
}

/* Instant scrolling for users who prefer reduced motion */
@media (prefers-reduced-motion: reduce) {
    html {
        scroll-behavior: auto;
    }
}

JavaScript Smooth Scrolling (More Control)

JAVASCRIPT
<a href="#section-2" class="smooth-scroll">Jump to Section 2</a>

<script>
document.querySelectorAll('a.smooth-scroll').forEach(anchor => {
    anchor.addEventListener('click', function(e) {
        e.preventDefault();
        
        const targetId = this.getAttribute('href');
        const targetElement = document.querySelector(targetId);
        
        targetElement.scrollIntoView({
            behavior: 'smooth',
            block: 'start'
        });
        
        // Update URL without jumping
        history.pushState(null, null, targetId);
    });
});
</script>

Scroll Offset for Fixed Headers

When you have a fixed header, anchors can scroll behind it. Fix this with CSS:

Scroll Padding Top
CSS
/* If you have a 60px fixed header */
header {
    position: fixed;
    top: 0;
    height: 60px;
    background: white;
    z-index: 100;
}

/* Add scroll padding to account for fixed header */
html {
    scroll-padding-top: 70px; /* Header height + 10px buffer */
}

/* Or apply to specific sections */
section {
    scroll-margin-top: 70px;
}
Alternative: Invisible Anchor Points
HTML
<section>
    <!-- Invisible anchor positioned above visible heading --&gt;
    <span id="features" class="anchor-offset"></span>
    <h2>Features</h2>
    <p>Content...</p>
</section>

<style>
.anchor-offset {
    display: block;
    position: relative;
    top: -70px; /* Negative offset for fixed header */
    visibility: hidden;
}
</style>

Highlighting Current Section

Automatically highlight the current section in your navigation:

Intersection Observer for Active Links
JAVASCRIPT
<nav id="toc">
    <a href="#section-1" class="toc-link">Section 1</a>
    <a href="#section-2" class="toc-link">Section 2</a>
    <a href="#section-3" class="toc-link">Section 3</a>
</nav>

<section id="section-1">...</section>
<section id="section-2">...</section>
<section id="section-3">...</section>

<style>
.toc-link.active {
    font-weight: bold;
    color: #007bff;
    border-left: 3px solid #007bff;
    padding-left: 8px;
}
</style>

<script>
const sections = document.querySelectorAll('section[id]');
const tocLinks = document.querySelectorAll('.toc-link');

const observer = new IntersectionObserver((entries) => {
    entries.forEach(entry => {
        if (entry.isIntersecting) {
            // Remove active class from all links
            tocLinks.forEach(link => link.classList.remove('active'));
            
            // Add active class to current section's link
            const activeLink = document.querySelector(`.toc-link[href="#${entry.target.id}"]`);
            if (activeLink) {
                activeLink.classList.add('active');
            }
        }
    });
}, {
    rootMargin: '-20% 0px -70% 0px' // Trigger when section is in viewport
});

sections.forEach(section => observer.observe(section));
</script>

FAQ Accordion with Anchors

Link directly to specific FAQ items:

Linkable FAQ Items
HTML
<section class="faq">
    <h2>Frequently Asked Questions</h2>
    
    <div class="faq-item" id="faq-1">
        <h3>
            <a href="#faq-1">What is HTML?</a>
        </h3>
        <p>HTML stands for HyperText Markup Language...</p>
    </div>
    
    <div class="faq-item" id="faq-2">
        <h3>
            <a href="#faq-2">Is HTML a programming language?</a>
        </h3>
        <p>No, HTML is a markup language, not a programming language...</p>
    </div>
    
    <div class="faq-item" id="faq-3">
        <h3>
            <a href="#faq-3">Do I need to know CSS?</a>
        </h3>
        <p>While you can write HTML without CSS...</p>
    </div>
</section>

<style>
.faq-item {
    margin: 1.5rem 0;
    padding: 1rem;
    border: 1px solid #ddd;
    border-radius: 5px;
}

.faq-item:target {
    background-color: #fff3cd;
    border-color: #ffc107;
}

.faq-item h3 a {
    color: inherit;
    text-decoration: none;
}

.faq-item h3 a:hover {
    text-decoration: underline;
}
</style>
💡
The :target Pseudo-Class: CSS automatically applies :targetto the element that matches the current URL fragment (the part after #).

Styling the :target Element

Use CSS to highlight the targeted element:

:target Styling Examples
CSS
/* Highlight targeted section */
section:target {
    background-color: #ffffcc;
    border-left: 5px solid #ffcc00;
    padding-left: 15px;
    animation: highlight 2s ease-out;
}

@keyframes highlight {
    0% {
        background-color: #ffff00;
    }
    100% {
        background-color: #ffffcc;
    }
}

/* Add indicator to targeted heading */
h2:target::before {
    content: "→ ";
    color: #007bff;
    font-weight: bold;
}

/* Pulse animation for targeted element */
:target {
    animation: pulse 1s ease-in-out;
}

@keyframes pulse {
    0%, 100% {
        transform: scale(1);
    }
    50% {
        transform: scale(1.02);
    }
}

ID Naming Best Practices

✅ Good ID Names

  • id="introduction"
  • id="getting-started"
  • id="section-2"
  • id="contact-form"
  • id="pricing-table"

❌ Bad ID Names

  • id="1st-section" (starts with number)
  • id="my section" (contains space)
  • id="section#2" (invalid character)
  • id="Contact" (inconsistent casing)
  • id="a" (not descriptive)

ID Rules:

  • Must be unique on the page
  • Must start with a letter (a-z, A-Z)
  • Can contain letters, digits, hyphens, underscores, periods
  • Case-sensitive
  • No spaces allowed
  • Should be descriptive and meaningful

6. The Psychology of Navigation: Why Anchors Matter

User experience studies show that visitors are often intimidated by massive walls of text. Anchors serve as "Safety Nets." When a user sees a Table of Contents or a "Jump to Summary" link, they feel more in control of their reading experience.

Information Scent

Descriptive anchors provide 'information scent'—clues that tell the user exactly what they will find when they click, reducing cognitive load.

The F-Pattern

Users scan in an 'F' pattern. Placing anchors at key inflection points allows scanners to stop and dive deep exactly where they need to.

UX Rule: Never make an anchor link go to a generic "Section 1" or "Part A". Use keyword-rich text like "Jump to Technical Requirements" to help with SEO and user confidence.

7. Performance: Scrolling & The Browser Paint Loop

Modern browsers optimize smooth scrolling, but poorly implemented JavaScript scroll listeners can cause Layout Thrashing. When an anchor link is clicked, the browser must:

  1. Calculate the target element's bounding box.
  2. Update the URL fragment.
  3. Orchestrate the scroll animation (if smooth).
  4. Fire scroll and intersection events.

Performance Pro Tip: Use the CSSwill-change: transform; property on the body or scrolling container if you are implementing complex parallax effects alongside your anchors. This hints the browser to promote the layer to the GPU, ensuring 60fps scrolling.

8. Stateful Fragments: The Foundation of Client-Side Routing

In Single Page Applications (SPAs), the URL fragment is the primitive form of "State." By listening to the hashchangeevent, developers can create complex navigation systems without ever refreshing the page.

A Simple Hash-Based Router
JAVASCRIPT
// Simple Router Logic
window.addEventListener('hashchange', () => {
    const route = window.location.hash.slice(1) || 'home';
    loadContentForRoute(route);
});

function loadContentForRoute(route) {
    console.log(`Updating state for: ${route}`);
    // Update DOM dynamically based on fragment
}

9. Accessibility: The Focus Trap & Logical Flow

Scroll-jumping can disorient users, especially those using screen readers or keyboard navigation. When a user "jumps" to a section, the visual viewport moves, but the keyboard focusoften stays on the link they just clicked. This is a "Focus Trap."

Accessibility Requirement: Always ensure that after a jump, the target element (or its container) receives programmatic focus. This allows keyboard users to continue reading from the new location immediately.

10. Accessibility Best Practices

Make Anchors Accessible:

  • Descriptive link text: "Jump to Features section" is better than "Click here"
  • Keyboard navigation: All anchor links should be keyboard-accessible
  • Focus management: Target element should receive focus after jump
  • Skip links: Provide "Skip to content" for keyboard users
Focus Management
JAVASCRIPT
// Move focus to target element after scrolling
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
    anchor.addEventListener('click', function(e) {
        e.preventDefault();
        
        const targetId = this.getAttribute('href').substring(1);
        const targetElement = document.getElementById(targetId);
        
        if (targetElement) {
            // Scroll to element
            targetElement.scrollIntoView({ behavior: 'smooth' });
            
            // Set focus (make element focusable first if needed)
            if (!targetElement.hasAttribute('tabindex')) {
                targetElement.setAttribute('tabindex', '-1');
            }
            targetElement.focus();
        }
    });
});

Common Use Cases Summary

📋 Documentation

Table of contents, section navigation, API reference

📰 Long Articles

Skip to sections, back to top, related articles

🛍️ E-commerce

Product sections, reviews, specifications

❓ FAQs

Direct links to specific questions

📱 Single Page Apps

Section navigation, tabs, accordions

📚 Educational

Course modules, lesson sections, exercises

Best Practices Summary

✅ Do

  • Use descriptive, unique IDs
  • Add smooth scrolling with scroll-behavior
  • Respect prefers-reduced-motion
  • Account for fixed headers with scroll offset
  • Highlight targeted sections with :target
  • Test keyboard navigation
  • Manage focus after scrolling
  • Provide back to top links for long pages

❌ Don't

  • Use duplicate IDs on same page
  • Start IDs with numbers
  • Include spaces in IDs
  • Forget about fixed header overlap
  • Use anchor links for actions (use buttons)
  • Ignore accessibility considerations
  • Make anchor links too small to click
  • Forget to test smooth scrolling

What's Next?

You've completed the Links & Navigation chapter! Now let's explore images and graphics.