Loading Developer Playground

Loading ...

Skip to main content
ARIA ROLEWidget Roles

link

An interactive reference to an internal or external resource. Links are the fundamental navigation element of the web, allowing users to move between pages and resources.

Keyboard Support
Enter only
Native Element
<a href="...">
Required Attributes
Accessible Name

Overview

The link role identifies an element as a hyperlink to an internal or external resource. When activated, the link navigates the user to the target resource, which could be a different page, a section within the current page, or an external website.

Important: Always use the native <a> element with an href attribute when possible. The role="link" should only be used when you absolutely cannot use an anchor element.

Links vs. Buttons

Links navigate to a resource (page, section, file). Use for navigation actions.

Buttons perform an action (submit, toggle, calculate). Use for in-page interactions that don't change the URL.

Live Demo: Link Interactions

Standard Links

Internal page link

Not visited yet

Link with States

"About" has aria-current="page"

Icon Links with Accessible Names

Try with keyboard: Tab to focus links, then press Enter to activate. Note that Space does NOT activate links (unlike buttons). Screen readers announce links with their accessible name and target information.

Code Examples

Basic Usage

<!-- Native anchor element (Best Practice) -->
<a href="/about">About Us</a>

<!-- Link with descriptive text -->
<a href="/pricing">View our pricing plans</a>

<!-- External link with indication -->
<a href="https://example.com" target="_blank" rel="noopener noreferrer">
  Visit Example.com
  <span class="sr-only">(opens in new tab)</span>
</a>

<!-- AVOID: Using role="link" when <a> is available -->
<span role="link" tabindex="0">Don't do this</span>

Custom Link Element

<!-- Custom link when <a> cannot be used -->
<span 
  role="link"
  tabindex="0"
  onclick="navigateTo('/page')"
  onkeydown="handleLinkKeydown(event, '/page')"
  class="custom-link"
>
  Custom Navigation Link
</span>

<script>
  function navigateTo(url) {
    window.location.href = url;
  }
  
  function handleLinkKeydown(event, url) {
    // Links activate on Enter only (not Space like buttons)
    if (event.key === 'Enter') {
      navigateTo(url);
    }
  }
</script>

<style>
  .custom-link {
    color: #0066cc;
    text-decoration: underline;
    cursor: pointer;
  }
  .custom-link:hover {
    color: #004499;
  }
  .custom-link:focus {
    outline: 2px solid #0066cc;
    outline-offset: 2px;
  }
</style>

Descriptive Link Text

<!-- Good: Descriptive link text -->
<a href="/annual-report-2024.pdf">
  Download the 2024 Annual Report (PDF, 2.4MB)
</a>

<!-- Good: Context from surrounding content -->
<p>
  Learn more about our accessibility initiatives in our
  <a href="/accessibility-statement">accessibility statement</a>.
</p>

<!-- Bad: Vague link text (avoid) -->
<a href="/page">Click here</a>
<a href="/docs">Read more</a>
<a href="/info">Learn more</a>

<!-- Better alternatives -->
<a href="/page">View product details</a>
<a href="/docs">Read the documentation</a>
<a href="/info">Learn about our services</a>

Image & Icon Links

<!-- Image link with alt text as accessible name -->
<a href="/home">
  <img src="/logo.png" alt="Company Name - Go to homepage">
</a>

<!-- Icon link with visually hidden text -->
<a href="/settings" class="icon-link">
  <svg aria-hidden="true" class="icon">...</svg>
  <span class="sr-only">Settings</span>
</a>

<!-- Image with separate link text -->
<a href="/product">
  <img src="/product.jpg" alt="">
  <span>View Product Details</span>
</a>

<!-- Screen reader only class -->
<style>
  .sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
  }
</style>

Link States

<!-- Current page indicator -->
<nav>
  <a href="/home">Home</a>
  <a href="/about" aria-current="page">About</a>
  <a href="/contact">Contact</a>
</nav>

<!-- Disabled/non-interactive link -->
<a 
  href="/premium-feature"
  aria-disabled="true"
  tabindex="-1"
  class="disabled-link"
>
  Premium Feature (Upgrade Required)
</a>

<!-- Link with expanded state (disclosure) -->
<a 
  href="#section-content"
  aria-expanded="false"
  aria-controls="section-content"
  onclick="toggleSection()"
>
  Show More Details
</a>

<style>
  .disabled-link {
    color: #999;
    pointer-events: none;
    text-decoration: none;
  }
</style>

React Components

// React Link Components
import { useState } from 'react';
import Link from 'next/link'; // or react-router-dom

// Basic internal link
function InternalLink({ href, children }) {
  return (
    <Link 
      href={href}
      className="text-blue-600 hover:text-blue-800 underline"
    >
      {children}
    </Link>
  );
}

// External link with new tab indicator
function ExternalLink({ href, children }) {
  return (
    <a
      href={href}
      target="_blank"
      rel="noopener noreferrer"
      className="text-blue-600 hover:text-blue-800 underline inline-flex items-center gap-1"
    >
      {children}
      <svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
        <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} 
          d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14" />
      </svg>
      <span className="sr-only">(opens in new tab)</span>
    </a>
  );
}

// Icon-only link with accessible name
function IconLink({ href, icon: Icon, label }) {
  return (
    <a
      href={href}
      aria-label={label}
      className="p-2 rounded-lg hover:bg-gray-100 focus:ring-2 focus:ring-blue-500"
    >
      <Icon className="w-6 h-6" aria-hidden="true" />
    </a>
  );
}

// Download link
function DownloadLink({ href, fileName, fileSize }) {
  return (
    <a
      href={href}
      download={fileName}
      className="inline-flex items-center gap-2 text-blue-600 hover:text-blue-800"
    >
      <span>Download {fileName}</span>
      <span className="text-gray-500 text-sm">({fileSize})</span>
    </a>
  );
}

// Skip link for accessibility
function SkipLink() {
  return (
    <a
      href="#main-content"
      className="sr-only focus:not-sr-only focus:absolute focus:top-4 focus:left-4 
                 bg-blue-600 text-white px-4 py-2 rounded-lg z-50"
    >
      Skip to main content
    </a>
  );
}

Keyboard Support

EnterActivates the link

The only key that activates links. This is different from buttons which also respond to Space.

TabMoves focus to the next focusable element

Links are included in the natural tab order. Ensure links have visible focus indicators.

Space Key Does NOT Activate Links

Unlike buttons, the Space key should NOT activate links. When implementingrole="link"on custom elements, only handle the Enter key. Space should scroll the page as expected.

Best Practices

Use native <a href="..."> element whenever possible

Provide descriptive, unique link text that makes sense out of context

Indicate when links open in new tabs (visually and for screen readers)

Use aria-current="page" for the current page in navigation

Ensure links have visible focus indicators (at least 3:1 contrast)

Provide file type and size for download links (e.g., "PDF, 2.4MB")

×

Don't use vague link text like "click here", "read more", or "learn more"

×

Don't use links for actions that don't navigate - use buttons instead

×

Don't remove underlines from links without providing another visual indicator

×

Don't use role="link" when you can use <a> with href attribute

Supported ARIA Attributes

Common Use Cases

Navigation menus
In-page anchor links
Breadcrumb trails
Pagination controls
Skip navigation links
Table of contents
External resource links
Download links
Email/phone links (mailto:, tel:)
Social media links
Footer site links
Related content links

Accessibility Notes

Descriptive Link Text

Screen reader users often navigate by links alone, hearing a list of all links on the page. Link text should make sense out of context. Instead of "Click here to view pricing", use "View pricing plans". The link text itself should describe the destination.

External Links & New Windows

When links open in a new window or tab, inform users both visually (with an icon) and for screen readers (with visually hidden text like "opens in new tab"). This helps users understand they'll be navigating away and their context will change.

Visual Distinction

Links should be visually distinguishable from surrounding text. The default underline works well, but if you remove it, you must provide another indicator that doesn't rely on color alone (like font weight, border, or icon). WCAG requires 3:1 contrast between link and non-link text when not using underlines.

Skip Links

Provide a "Skip to main content" link as the first focusable element on the page. This allows keyboard users to bypass repetitive navigation. The link should be visually hidden until focused, then become visible.

Related Roles & Attributes

Specifications & Resources