Linkagent

Internal Links in HTML: Syntax, Anchors, Jump Links

The complete HTML internal link reference: <a href> syntax, relative vs absolute paths, jump links with id fragments, and accessible link text.

Nedim Mehić

Nedim Mehić

August 9, 2026 · 7 min read

Internal Links in HTML: Syntax, Anchors, Jump Links

An internal link in HTML is an <a> element whose href points to another page on the same site: <a href="/pricing">See pricing</a>. That's the whole mechanism, but the details around it (relative vs. absolute paths, fragment identifiers for jump links, link text that works for screen readers and search engines) are where pages quietly go wrong. This is the practical reference for all of it, with copy-pasteable examples.

The basic syntax

<a href="/blog/topic-clusters">our guide to topic clusters</a>

Three parts matter:

  • <a>: the anchor element. Only <a> with an href creates a real link; an <a> without href is a placeholder that isn't focusable or announced as a link.
  • href: the destination URL.
  • The link text (everything between the tags): the anchor text. It's UI for humans, context for screen readers, and a relevance signal for search engines. More on getting it right below.

What makes a link internal is simply that the destination resolves to the same site. The browser doesn't care; your information architecture does. Internal links are how readers and crawlers move through your site, and collectively they form the structure that our complete guide to internal linking covers from the strategy side. This post stays on the syntax side.

Relative vs. absolute: which href form to use

The same page can be referenced several ways:

<!-- Root-relative: starts with / (resolves from the domain root) -->
<a href="/blog/pillar-pages">pillar pages</a>

<!-- Document-relative: resolves from the current page's location -->
<a href="../guides/pillar-pages">pillar pages</a>

<!-- Absolute: full scheme and host -->
<a href="https://example.com/blog/pillar-pages">pillar pages</a>

Use root-relative paths (/blog/pillar-pages) for internal links in almost all cases. They survive domain changes (staging → production, http → https, domain migrations) without rewrites, they're shorter, and they can't accidentally point at the wrong environment.

Document-relative paths (../guides/page) break silently when a page moves or when the same content renders at two URL depths (a common CMS behavior). They're fine inside self-contained documentation trees; risky in CMS content.

Absolute URLs for internal links aren't wrong: search engines handle them fine, but they hardcode the host, so a staging crawl links to production, and a future domain change means editing every link. Reserve absolute URLs for feeds, emails, and canonical/og tags, where context is lost and a full URL is required.

One subtlety worth knowing: a <base href> tag in the document head changes how relative URLs resolve for the whole page. If links break mysteriously after a template change, check for a <base> tag.

Be consistent about trailing slashes and case. /Blog/Pillar-Pages/ and /blog/pillar-pages are different URLs to a crawler. Pick one canonical form per page and always link to it; anything else spends crawl budget on redirects, or worse, splits signals across duplicates.

Jump links: id attributes and fragments

A jump link (anchor link) targets a specific position within a page, using an element id and a URL fragment.

Step 1: give the target element an id:

<h2 id="updating-cadence">Updating cadence</h2>

Step 2: link to it with #:

<!-- From within the same page (a table of contents): -->
<a href="#updating-cadence">Updating cadence</a>

<!-- From another page: fragment appended to the path -->
<a href="/blog/pillar-pages#updating-cadence">how often to update a pillar page</a>

Rules and gotchas:

  • id values must be unique per page. Duplicate ids mean the browser jumps to the first match and the rest are unreachable.
  • Ids are case-sensitive. #Updating-Cadence will not find id="updating-cadence".
  • Put the id on the heading itself, not an empty <a name> above it; name on anchors is the obsolete pre-HTML5 approach.
  • Prefer stable, readable, kebab-case ids derived from the heading text. If you rename ids, inbound fragment links break silently: the browser lands at the top of the page with no error, which is why fragment rot is so common.
  • Fragments are handled client-side. Search engines index the page, not each fragment, as a separate document; jump links are a usability feature (and can appear as sitelink-style jump-to entries), not a way to multiply indexed pages.
  • Sticky headers overlap jump targets. Fix with CSS: scroll-margin-top: 80px on the target (or scroll-padding-top on the scroll container), and html { scroll-behavior: smooth } if you want smooth scrolling without JavaScript.

If your source files are Markdown rather than raw HTML, the ids are generated for you from heading text, by rules that differ per platform. Our companion reference on internal links in Markdown covers the slug rules for GitHub, Obsidian, MkDocs, and Docusaurus.

The title attribute: myths vs. reality

<!-- Widely cargo-culted, mostly useless: -->
<a href="/pricing" title="pricing page">Pricing</a>

Persistent myths about title on links: that it boosts SEO (there is no evidence search engines use it as a ranking signal; anchor text is what carries meaning), and that it helps accessibility (mostly the opposite: many screen reader configurations don't announce it, and it never appears for touch or keyboard users; it's a mouse-hover-only tooltip).

The practical guidance: put the important words in the link text, not in title. If you find yourself writing a title because the link text is vague, fix the link text. A title that merely repeats the link text is noise; delete it. Rare legitimate use: supplementary hint text you're comfortable with most users never seeing.

Accessible link text (which is also SEO-correct link text)

Screen reader users commonly navigate by pulling up a list of all links on the page, hearing each link's text out of context. That single fact generates all the rules:

  • The link text alone should identify the destination. "Read our guide to canonical tags" works in isolation; "click here" produces a list that reads "here, here, learn more, here."
  • Never use "here", "this", or bare "read more" as complete link text. If repeated teaser links are unavoidable in a card layout, differentiate them for assistive tech (aria-label="Read more: pillar page anatomy"); but prose links should just carry real text.
  • Don't start every link with "link to": screen readers already announce the element as a link.
  • Keep it a phrase, not a paragraph. The natural noun phrase that names the destination (typically 2–8 words) is right for humans and, not coincidentally, right for search engines, which read anchor text as a description of the target page.
  • Links must be visually distinguishable by more than color alone (underlines are the convention worth keeping), and every link must show a visible focus state for keyboard users.

The overlap is the point: descriptive anchors serve accessibility and SEO with the same text; the details of choosing those words are covered in our sibling piece from the strategy side. And the same principle governs the difference between internal and external links: the syntax is identical, but internal anchors are entirely under your control, so there's no excuse for vague ones.

One more attribute myth

You do not need rel="nofollow", target="_blank", or rel="noopener" on internal links. Nofollow tells search engines to distrust your own page. Opening same-site links in new tabs breaks the back button and user expectations. Keep internal links plain: an href and good text.

Common HTML internal-link mistakes

A field checklist, in rough order of frequency:

  1. Vague anchors: "here", "this post", "read more" as the linked words.
  2. Linking to redirects: internal hrefs pointing at URLs that 301 elsewhere. Update the href to the final destination.
  3. Broken fragments: jump links whose target id was renamed; they fail silently.
  4. Mixed URL forms: linking the same page as /page, /page/, and https://site.com/page in different places.
  5. JavaScript-only "links": <div onclick> or <a href="#"> with a click handler. Not crawlable as links, not keyboard-accessible. If it navigates, it's an <a href>.
  6. Links only in menus: the page is reachable, but never referenced in prose. Search engines treat contextual in-text links very differently from boilerplate navigation, which is why an audit that counts nav links can say "fine" while the in-text graph says "orphan."

Auditing these by hand works for a ten-page site. Beyond that, run an internal link checker against the site; a crawl surfaces broken links, redirected hrefs, orphans, and vague anchors across every page at once, including the in-prose-vs-navigation distinction that manual spot checks miss.

Complete reference example

Everything above in one snippet:

<article>
  <h2 id="choosing-anchors">Choosing anchor text</h2>
  <p>
    Anchor text should describe its destination. When a paragraph
    mentions structuring a content hub, that sentence is the natural
    home for a link to
    <a href="/blog/topic-clusters">building topic clusters properly</a>.
    The linked words already name the concept.
  </p>
  <p>
    For position-specific references, combine a path and fragment:
    see <a href="/blog/pillar-pages#updating-cadence">how often to
    update a pillar page</a>.
  </p>
</article>

Root-relative paths, unique kebab-case ids, fragments for in-page targets, descriptive text as the anchor, no title attributes, no nofollow, no new tabs. That's the entire craft of the HTML side; the harder question of which pages should link to which is strategy, and that's the other half of the discipline.

Related reading

Put this on autopilot

Linkagent finds and ships internal links for you. Scan your site free, no account needed.

Free scan, no account needed. Takes about 20 seconds.