< a >
The anchor tag: more versatile than you may know
A native hyperlink. HTML gives you navigation, browser history, referrer policy, middle-click, Cmd/Ctrl-click, right-click context menu, drag-to-bookmark, prefetching hints, link decoration, visited state, and the correct assistive technology role. All of this is built in. The anchor element is one of the oldest elements in HTML and has quietly gained new capabilities over the years that are worth a fresh look.
Built-in with native HTML
- Middle-click opens in a new tab. The user's mouse does this without any code. Elements that aren't real anchors don't participate.
- Cmd/Ctrl-click opens in a new tab. Same behavior, same requirement.
- Right-click, then Copy Link Address. Requires a real
hrefon a real anchor. - Drag-to-bookmark, drag-to-address-bar. Requires a real
href. - Visited state (
:visitedpseudo-class). Real anchors with real hrefs get this. Users rely on it more than designers realize. - Screen reader "links list" navigation. Assistive technology users often pull up a list of all links on a page as a primary way to navigate. Real anchors with real hrefs populate that list.
- The
hrefdisplays in the browser's status bar on hover. Many users check this before clicking. Built-in, no tooltip needed.
All of these come with the element itself, as long as it has a real href value. The pattern for single-page-app routing is to let the anchor be a real anchor with a real URL. A router can still intercept the click and do in-app navigation underneath. Modern SPA router libraries do exactly this: they render a real <a> with a real href and enhance it with client-side routing.
href is the load-bearing attribute
An <a> without href is, by the HTML specification's own language, a "placeholder link." It:
- is not focusable by default
- has no role in the accessibility tree
- does not receive
:linkor:visitedstyling - is not activated by the Enter key
If an anchor has no destination, it's worth considering whether the element you actually want is a <button>. Buttons are purpose-built for actions, and anchors are purpose-built for navigation. When there's no destination, there's no navigation.
The href="#" value is a related pattern worth thinking through. A single # is a valid URL fragment, and navigating to it mutates the current URL, scrolls the page to the top, and pushes a browser history entry. For a link that is meant to do something rather than navigate somewhere, a button is a cleaner fit.
Link relationship attributes that matter
The rel attribute carries real weight. Several values change browser behavior meaningfully:
rel="noopener"opens the linked page in a new window without giving that page a reference back to the opener. Without noopener, the destination page can, through JavaScript, navigate the opener page to a new URL. Modern browsers default tonoopenerbehavior fortarget="_blank"links, though declaring it explicitly remains a good habit.rel="noreferrer"suppresses theRefererheader so the destination doesn't see which page the user came from. It also implies noopener.rel="nofollow",rel="ugc", andrel="sponsored"are signals to search engines. Relevant on any page that accepts user-generated content or carries sponsored links.rel="alternate"paired withhreflangindicates a translated or regional version of the same page.rel="me"is the IndieWeb identity verification mechanism. It is how Mastodon profile links, personal site backlinks, and IndieAuth flows all verify that one URL belongs to the same person as another. One attribute value replaces a meaningful amount of OAuth machinery for federated identity linking.
target="_blank" considerations
The common pattern for an external link that opens in a new tab:
<a href="https://external.example.com" target="_blank" rel="noopener noreferrer">
External link
</a>
Three things to think about:
- Security: noopener, as above.
- Privacy: noreferrer if the destination shouldn't know the source page.
- Accessibility: when a link opens in a new tab, the user deserves to know. Either a visible icon, visually hidden text like "(opens in new tab)" inside the accessible name, or both. Sighted users lose their back button, and screen reader users don't get a context-switch announcement by default.
Downloads, mail, tel, sms
Four things the anchor can do that are often delegated to JavaScript:
- The
downloadattribute turns any anchor into a download trigger. An optional value sets the suggested filename:<a href="/report.pdf" download="Q3-report.pdf">. The filename override only applies to same-origin resources. mailto:URLs support?subject=,&body=,&cc=,&bcc=. All values need to be URL-encoded. A pre-filled contact email is a single element with no script.tel:dials on mobile and opens FaceTime, Skype, or a similar call handler on desktop. Format numbers as international:tel:+15035551234.sms:composes a text message.sms:+15035551234?body=Hellopre-fills the body.
Taken together, a "share this page" component that offers email and SMS as share targets is two anchors with no script at all.
URL fragments and text fragments
<a href="#section-id"> is native in-page navigation. Paired with scroll-behavior: smooth on the root and the :target pseudo-class in CSS, it covers smooth scroll on click and the ability to style the currently-targeted section. No listener, no ref, no scroll library.
Text fragments go further. The URL can link to a specific phrase inside a page, even when the page author never marked it up:
<a href="https://example.com/article#:~:text=the%20exact%20phrase">
Jump to the phrase in context
</a>
Supported in Chromium and Safari. Useful for documentation, citations, and any "see this specific line" pattern.
Composite patterns that use <a> well
Patterns where the anchor is the right element and a different element would break the pattern:
- Breadcrumb trails. Each crumb is a navigation to a parent location, so each crumb is an anchor inside a
<nav>landmark with an ordered list. - Pagination. Page numbers are navigations. Even in a single-page application, pagination deserves real anchors with real URLs so the page state is shareable and the back button works as expected.
- Skip links. The first focusable element on a page, usually visually hidden until focused:
<a href="#main">Skip to content</a>. One of the highest-value accessibility additions a page can have. - Tables of contents. In-page anchor jumps to section headings, paired with a
<nav>landmark and often anaria-label. - Tag and filter lists. When each tag links to a filtered view with its own URL, the state is bookmarkable and shareable natively.
Already HTML-available
Patterns that HTML handles natively, which JavaScript is often asked to do instead:
- Clickable containers wired to client-side routing. When the element is a real anchor with a real
href, middle-click, Cmd/Ctrl-click, right-click, drag-to-bookmark, visited state, and the links-list for assistive technology all work without additional code. - Anchors with
href="#"wired to click handlers. For actions rather than navigation, the<button>element is built for that job. - Smooth scroll to in-page sections.
scroll-behavior: smoothin CSS and a fragment URL cover this case. - Copy-to-clipboard for sharing. The browser's built-in "copy link" on a right-click covers it without any code. A copy button still makes sense for polish, and it can sit alongside a real anchor rather than replacing it.
- Prefilled contact flows.
mailto:andsms:with query parameters pre-fill the message without any script.
Reference:
- WHATWG
- the-a-element
- caniuse.com
- mdn-html_elements_a
- MDN Docs
- Web/HTML/Element/a
- Link types (rel values)
- WAI-ARIA APG
- Link Pattern
- web.dev
- Text Fragments