HTML <a> reference
Jump to this section
Common attributes Jump to this section
Basic link structure Jump to this section
An <a> (anchor) element creates a hyperlink to web pages, files, email addresses, locations in the same page, or anything else a URL can address.
<a href="https://example.com">Visit Example</a>href Jump to this section
The hyperlink reference - the URL the link points to. This is the most important attribute and defines where the link navigates.
Common URL types:
- Absolute:
https://example.com - Relative:
/about,../page.html - Anchor:
#section-id - Email:
mailto:user@example.com - Phone:
tel:+1234567890 - JavaScript:
javascript:void(0)(avoid when possible)
<!-- External link -->
<a href="https://example.com">External Site</a>
<!-- Relative link -->
<a href="/about">About Page</a>
<!-- Page anchor -->
<a href="#features">Jump to Features</a>
<!-- Email link -->
<a href="mailto:hello@example.com">Email Us</a>
<!-- Phone link -->
<a href="tel:+1234567890">Call Us</a>
<!-- File download -->
<a href="/files/document.pdf">Download PDF</a>
target Jump to this section
Specifies where to open the linked document.
Values:
_self(default): Opens in the same browsing context_blank: Opens in a new tab or window_parent: Opens in the parent frame_top: Opens in the top-most frame
<a href="https://example.com"
target="_blank"
rel="noopener noreferrer">
Open in New Tab
</a>Security note: When using target="_blank", always include rel="noopener noreferrer" to prevent security vulnerabilities and performance issues.
rel Jump to this section
Specifies the relationship between the current document and the linked document. Important for security, SEO, and functionality.
Common values:
noopener: Prevents the new page from accessingwindow.openernoreferrer: Prevents the browser from sending the referrer headernofollow: Tells search engines not to follow this linksponsored: Marks the link as sponsored contentugc: User-generated content (like comments)external: Indicates an external linkhelp: Links to help documentationprev/next: Previous/next in a sequence
<!-- External link (security) -->
<a href="https://example.com"
target="_blank"
rel="noopener noreferrer">
External Link
</a>
<!-- Sponsored link (SEO) -->
<a href="https://sponsor.com" rel="sponsored nofollow">
Sponsored Link
</a>
<!-- User content link (SEO) -->
<a href="https://user-site.com" rel="ugc nofollow">
User's Website
</a>
<!-- Pagination -->
<a href="/page/2" rel="next">Next Page</a>
download Jump to this section
Prompts the user to download the linked resource instead of navigating to it. The attribute value becomes the suggested filename.
<a href="/files/report.pdf" download="monthly-report.pdf">
Download Report
</a>
<!-- Browser suggests filename -->
<a href="/files/data.csv" download>
Download CSV
</a>
Note: Download only works for same-origin URLs or blob/data URLs. Cross-origin files require appropriate CORS headers.
hreflang Jump to this section
Indicates the language of the linked document. Helpful for search engines and browsers.
<a href="/es/about" hreflang="es">Acerca de</a>
<a href="/fr/contact" hreflang="fr">Contact</a>
<a href="/de/home" hreflang="de">Startseite</a>
type Jump to this section
Specifies the MIME type of the linked resource. Helps browsers handle the link appropriately.
<a href="/document.pdf" type="application/pdf">PDF Document</a>
<a href="/video.mp4" type="video/mp4">Watch Video</a>
<a href="/feed.xml" type="application/rss+xml">RSS Feed</a>
ping Jump to this section
Specifies URLs to be notified when the user follows the link. Used for tracking (privacy-conscious alternative to JavaScript tracking).
<a href="https://example.com"
ping="https://analytics.example.com/track">
Tracked Link
</a>
Privacy note: Some browsers may ignore this attribute based on user privacy settings.
referrerpolicy Jump to this section
Controls how much referrer information is sent when following the link.
Values:
no-referrer: Never send referrerno-referrer-when-downgrade: Don't send when going from HTTPS to HTTPorigin: Send only the origin (domain)origin-when-cross-origin: Full URL for same-origin, origin only for cross-originsame-origin: Send referrer only for same-origin requestsstrict-origin: Like origin, but not on HTTPS to HTTPstrict-origin-when-cross-origin(default): Full URL same-origin, origin cross-originunsafe-url: Always send full URL (not recommended)
<a href="https://example.com"
referrerpolicy="no-referrer">
Private Link
</a>
<a href="https://example.com"
referrerpolicy="origin">
Send Origin Only
</a>
Accessibility attributes Jump to this section
aria-label Jump to this section
Provides an accessible label when the link text alone isn't descriptive enough.
<!-- Icon-only link -->
<a href="/settings" aria-label="Account Settings">
⚙️
</a>
<!-- Ambiguous text -->
<a href="/article/1" aria-label="Read more about accessibility">
Read more
</a>
aria-describedby Jump to this section
References additional descriptive text by its id to provide more context.
<a href="/premium" aria-describedby="premium-description">
Upgrade to Premium
</a>
<span id="premium-description">
Get unlimited access for $9.99/month
</span>
aria-current Jump to this section
Indicates which link represents the current page/location. Important for navigation.
Values: page, step, location, date, time, true, false
<nav>
<a href="/" aria-current="page">Home</a>
<a href="/about">About</a>
<a href="/contact">Contact</a>
</nav>
aria-disabled Jump to this section
Indicates the link is disabled. Unlike buttons, links don't have a native disabled state.
<a href="#" aria-disabled="true"
style="pointer-events: none; opacity: 0.5;">
Unavailable Link
</a>
tabindex Jump to this section
Controls keyboard focus order. Links are naturally focusable, so this is rarely needed.
<!-- Remove from tab order -->
<a href="javascript:void(0)" tabindex="-1">Not Keyboard Accessible</a>
<!-- Custom tab order (avoid if possible) -->
<a href="javascript:void(0)" tabindex="1">First Tab Stop</a>
Other common attributes Jump to this section
id Jump to this section
Unique identifier for the link. Can be used as a target for anchor navigation.
<a href="#section-1">Go to Section 1</a>
<!-- Later in the document -->
<h2 id="section-1">Section 1</h2>
class Jump to this section
Assigns CSS class names for styling or JavaScript selection.
<a href="/docs" class="button button-primary">
View Documentation
</a>
title Jump to this section
Provides additional information as a tooltip on hover. Not accessible to keyboard-only users or mobile, so don't rely on it for critical information.
<a href="/help" title="Get help and support">
Help
</a>
data-* attributes Jump to this section
Custom attributes for storing application-specific data on the link.
<a href="/product/123"
data-product-id="123"
data-category="electronics">
View Product
</a>
<script>
const link = document.querySelector('a');
const productId = link.dataset.productId; // "123"
const category = link.dataset.category; // "electronics"
</script>
style Jump to this section
Inline CSS styles. Generally prefer external stylesheets or classes.
<a href="/important"
style="color: red; font-weight: bold;">
Important Link
</a>
Link types and patterns Jump to this section
Page anchor links Jump to this section
Link to specific sections within the same page.
<a href="#section-id">Jump to Section</a>
<!-- Target element -->
<section id="section-id">
<h2>Section Title</h2>
</section>
Email links Jump to this section
Open the user's email client with pre-filled information.
<!-- Basic email -->
<a href="mailto:hello@example.com">Email Us</a>
<!-- With subject -->
<a href="mailto:support@example.com?subject=Help Request">
Support
</a>
<!-- With subject and body -->
<a href="mailto:info@example.com?subject=Inquiry&body=Hello,">
Contact
</a>
<!-- Multiple recipients -->
<a href="mailto:one@example.com,two@example.com">
Email Multiple
</a>
<!-- CC and BCC -->
<a href="mailto:to@example.com?cc=copy@example.com&bcc=hidden@example.com">
Email with CC/BCC
</a>
Phone links Jump to this section
Initiate phone calls on devices with calling capability.
<!-- Basic phone link -->
<a href="tel:+1234567890">Call Us</a>
<!-- With extension -->
<a href="tel:+1234567890,,,123">Call (ext. 123)</a>
<!-- International format -->
<a href="tel:+44-20-1234-5678">Call UK Office</a>
SMS links Jump to this section
Open SMS/messaging app with pre-filled content.
<!-- Basic SMS -->
<a href="sms:+1234567890">Send SMS</a>
<!-- With message body -->
<a href="sms:+1234567890?body=Hello!">Text Us</a>
<!-- iOS uses different syntax for body -->
<a href="sms:+1234567890&body=Hello!">Text Us (iOS)</a>
Other protocol links Jump to this section
<!-- WhatsApp -->
<a href="https://wa.me/1234567890">Chat on WhatsApp</a>
<!-- Skype -->
<a href="skype:username?call">Call on Skype</a>
<!-- FaceTime -->
<a href="facetime:email@example.com">FaceTime</a>
<!-- Maps -->
<a href="https://maps.google.com/?q=New+York">View on Maps</a>
<!-- App Store / Play Store -->
<a href="https://apps.apple.com/app/id123456">Download iOS App</a>
<a href="https://play.google.com/store/apps/details?id=com.app">
Download Android App
</a>
Styling basics Jump to this section
Links are highly customizable with CSS. Control appearance across different states (link, visited, hover, active, focus) to create engaging and accessible interfaces.
Link states (pseudo-classes) Jump to this section
Links have several states that should be styled in this order: :link, :visited, :hover, :focus, :active (remember: LoVe HAte).
/* Unvisited link */
a:link {
color: #3b82f6;
}
/* Visited link */
a:visited {
color: #8b5cf6;
}
/* Mouse hover */
a:hover {
color: #2563eb;
text-decoration: none;
}
/* Keyboard focus */
a:focus {
outline: 2px solid #93c5fd;
outline-offset: 2px;
}
/* Active (being clicked) */
a:active {
color: #1e40af;
}
Basic link styles Jump to this section
.link-basic {
color: #3b82f6;
text-decoration: underline;
}
.link-basic:hover {
color: #2563eb;
}
No underline (with hover effect) Jump to this section
.link-hover-underline {
color: #3b82f6;
text-decoration: none;
transition: color 0.2s;
}
.link-hover-underline:hover {
text-decoration: underline;
}
Button-style link Jump to this section
.link-button {
display: inline-block;
padding: 10px 20px;
background: #3b82f6;
color: white;
text-decoration: none;
border-radius: 6px;
font-weight: 500;
transition: background 0.2s;
}
.link-button:hover {
background: #2563eb;
}
Outlined button link Jump to this section
.link-outlined {
display: inline-block;
padding: 10px 20px;
border: 2px solid #3b82f6;
color: #3b82f6;
text-decoration: none;
border-radius: 6px;
font-weight: 500;
transition: all 0.2s;
}
.link-outlined:hover {
background: #3b82f6;
color: white;
}
Underline animation Jump to this section
.link-animated {
position: relative;
color: #3b82f6;
text-decoration: none;
padding-bottom: 2px;
}
.link-animated::after {
content: '';
position: absolute;
bottom: 0;
left: 0;
width: 0;
height: 2px;
background: #3b82f6;
transition: width 0.3s;
}
.link-animated:hover::after {
width: 100%;
}
Arrow link Jump to this section
.link-arrow {
color: #3b82f6;
text-decoration: none;
display: inline-flex;
align-items: center;
gap: 6px;
transition: gap 0.2s;
}
.link-arrow:hover {
gap: 10px;
}
Badge link Jump to this section
.link-badge {
display: inline-block;
padding: 4px 10px;
background: #dbeafe;
color: #1e40af;
text-decoration: none;
border-radius: 12px;
font-size: 13px;
font-weight: 500;
transition: background 0.2s;
}
.link-badge:hover {
background: #bfdbfe;
}
Card link Jump to this section
.link-card {
display: block;
padding: 20px;
border: 1px solid #e5e7eb;
border-radius: 8px;
text-decoration: none;
color: inherit;
transition: all 0.2s;
}
.link-card:hover {
border-color: #3b82f6;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}
Icon link Jump to this section
<a href="#" class="link-icon">
<svg width="20" height="20" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M12 6v6m0 0v6m0-6h6m-6 0H6"/>
</svg>
Add item
</a>
.link-icon {
display: inline-flex;
align-items: center;
gap: 8px;
color: #3b82f6;
text-decoration: none;
transition: color 0.2s;
}
.link-icon:hover {
color: #2563eb;
}
.link-icon svg {
width: 20px;
height: 20px;
}
External link indicator Jump to this section
<a href="https://example.com" target="_blank" rel="noopener" class="link-external">
External link
<svg width="14" height="14" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14"/>
</svg>
</a>
.link-external {
color: #3b82f6;
text-decoration: none;
display: inline-flex;
align-items: center;
gap: 4px;
}
/* Alternative with ::after pseudo-element */
.link-external::after {
content: '';
display: inline-block;
width: 14px;
height: 14px;
background-image: url('external-icon.svg');
}
Download link Jump to this section
<a href="/file.pdf" download class="link-download">
<svg width="18" height="18" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4"/>
</svg>
Download
</a>
.link-download {
display: inline-flex;
align-items: center;
gap: 8px;
padding: 8px 16px;
background: #10b981;
color: white;
text-decoration: none;
border-radius: 6px;
font-weight: 500;
transition: background 0.2s;
}
.link-download:hover {
background: #059669;
}
Disabled link Jump to this section
.link-disabled {
color: #9ca3af;
text-decoration: none;
cursor: not-allowed;
pointer-events: none;
opacity: 0.6;
}
/* Or with attribute selector */
a[aria-disabled="true"] {
color: #9ca3af;
cursor: not-allowed;
pointer-events: none;
}
Active navigation link Jump to this section
.nav-link {
color: #6b7280;
text-decoration: none;
padding-bottom: 4px;
border-bottom: 2px solid transparent;
transition: color 0.2s;
}
.nav-link:hover {
color: #374151;
}
.nav-link[aria-current="page"] {
color: #3b82f6;
font-weight: 600;
border-bottom-color: #3b82f6;
}
Focus styles (accessibility) Jump to this section
Always provide clear focus indicators for keyboard navigation.
.link-focus {
color: #3b82f6;
text-decoration: none;
padding: 8px 12px;
border-radius: 4px;
transition: all 0.2s;
}
.link-focus:focus {
outline: 2px solid #93c5fd;
outline-offset: 2px;
}
/* Visible focus only for keyboard users */
.link-focus:focus-visible {
outline: 2px solid #93c5fd;
outline-offset: 2px;
}
.link-focus:focus:not(:focus-visible) {
outline: none;
}
Social media links Jump to this section
.social-link {
display: flex;
align-items: center;
justify-content: center;
width: 40px;
height: 40px;
border-radius: 50%;
text-decoration: none;
transition: transform 0.2s;
}
.social-link:hover {
transform: scale(1.1);
}
.social-link.twitter { background: #1da1f2; }
.social-link.linkedin { background: #0077b5; }
.social-link.github { background: #333; }
JavaScript patterns Jump to this section
Links can be enhanced with JavaScript for tracking, dynamic behavior, smooth scrolling, and interactive features.
Prevent default navigation Jump to this section
Prevent the link from navigating and handle the action with JavaScript.
const link = document.getElementById('js-prevent');
const output = document.getElementById('prevent-output');
link.addEventListener('click', (e) => {
e.preventDefault(); // Prevent navigation
output.textContent = 'Navigation prevented!';
});
Smooth scroll to anchor Jump to this section
Smoothly scroll to page sections instead of jumping.
const smoothLinks = document.querySelectorAll('a[href^="#"]');
smoothLinks.forEach(link => {
link.addEventListener('click', (e) => {
e.preventDefault();
const targetId = link.getAttribute('href');
const target = document.querySelector(targetId);
if (target) {
target.scrollIntoView({
behavior: 'smooth',
block: 'start'
});
}
});
});
// CSS alternative
html {
scroll-behavior: smooth;
}
Confirm before navigation Jump to this section
Show a confirmation dialog for critical actions.
const dangerLink = document.getElementById('js-confirm');
dangerLink.addEventListener('click', (e) => {
const confirmed = confirm(
'Are you sure you want to delete your account?'
);
if (!confirmed) {
e.preventDefault();
}
// If confirmed, navigation proceeds normally
});
Track link clicks Jump to this section
Track when users click external links.
const trackedLinks = document.querySelectorAll('.js-track');
const trackOutput = document.getElementById('track-output');
trackedLinks.forEach(link => {
link.addEventListener('click', (e) => {
const url = link.href;
// Send to analytics
trackOutput.textContent = `Tracked: ${url}`;
// Example: Send to analytics service
// analytics.track('Link Click', { url: url });
// Don't prevent - let navigation happen
});
});
Copy link to clipboard Jump to this section
Add a "Copy link" button functionality.
<div style="display:flex;align-items:center;gap:12px;">
<a href="https://example.com/article" id="shareable-link">Article link</a>
<button id="copy-link-btn">Copy</button>
</div>
<div id="copy-status"></div>
const link = document.getElementById('shareable-link');
const copyBtn = document.getElementById('copy-link-btn');
const status = document.getElementById('copy-status');
copyBtn.addEventListener('click', async () => {
const url = link.href;
try {
await navigator.clipboard.writeText(url);
status.textContent = 'Link copied!';
setTimeout(() => {
status.textContent = '';
}, 2000);
} catch (err) {
status.textContent = 'Failed to copy';
status.style.color = '#dc2626';
}
});
Add target="_blank" to external links Jump to this section
Automatically open external links in new tabs.
// Select all links in content
const links = document.querySelectorAll('#content-area a');
links.forEach(link => {
const url = new URL(link.href, window.location.origin);
// Check if external
if (url.origin !== window.location.origin) {
link.setAttribute('target', '_blank');
link.setAttribute('rel', 'noopener noreferrer');
}
});
Dynamic link generation Jump to this section
Create links dynamically from data.
const container = document.getElementById('link-container');
const button = document.getElementById('generate-links');
const pages = [
{ title: 'Home', url: '/' },
{ title: 'About', url: '/about' },
{ title: 'Blog', url: '/blog' },
{ title: 'Contact', url: '/contact' }
];
button.addEventListener('click', () => {
container.innerHTML = '';
pages.forEach(page => {
const link = document.createElement('a');
link.href = page.url;
link.textContent = page.title;
link.style.color = '#3b82f6';
link.style.textDecoration = 'none';
container.appendChild(link);
});
});
Lazy load on click Jump to this section
Load content when a link is clicked instead of navigating.
const loadLink = document.getElementById('load-content');
const contentDiv = document.getElementById('loaded-content');
loadLink.addEventListener('click', async (e) => {
e.preventDefault();
loadLink.textContent = 'Loading...';
try {
const response = await fetch(loadLink.href);
const data = await response.text();
contentDiv.innerHTML = data;
contentDiv.style.display = 'block';
loadLink.textContent = 'Reload content';
} catch (err) {
contentDiv.textContent = 'Failed to load content';
contentDiv.style.display = 'block';
loadLink.textContent = 'Try again';
}
});
Toggle active state Jump to this section
Toggle active state on navigation links.
const navLinks = document.querySelectorAll('#nav-menu a');
navLinks.forEach(link => {
link.addEventListener('click', (e) => {
e.preventDefault();
// Remove active from all
navLinks.forEach(l => {
l.style.color = '#6b7280';
l.style.fontWeight = '400';
l.style.background = 'transparent';
});
// Add active to clicked
link.style.color = '#3b82f6';
link.style.fontWeight = '600';
link.style.background = '#eff6ff';
});
});
Prefetch on hover Jump to this section
Prefetch page content when hovering over links for faster navigation.
const prefetchLinks = document.querySelectorAll('.prefetch-link');
const status = document.getElementById('prefetch-status');
prefetchLinks.forEach(link => {
let prefetched = false;
link.addEventListener('mouseenter', () => {
if (prefetched) return;
const url = link.href;
status.textContent = 'Prefetching...';
// Create prefetch link element
const prefetchLink = document.createElement('link');
prefetchLink.rel = 'prefetch';
prefetchLink.href = url;
document.head.appendChild(prefetchLink);
prefetched = true;
status.textContent = 'Prefetched!';
setTimeout(() => {
status.textContent = '';
}, 2000);
});
});
Tooltip on hover Jump to this section
Show custom tooltip when hovering over links.
<div style="position:relative;display:inline-block;">
<a href="#" id="tooltip-link">Hover for tooltip</a>
<div id="custom-tooltip" style="position:absolute;bottom:calc(100% + 8px);left:50%;transform:translateX(-50%);padding:6px 12px;background:#1f2937;color:white;border-radius:6px;font-size:13px;white-space:nowrap;display:none;pointer-events:none;">
Click to learn more
<div style="position:absolute;top:100%;left:50%;transform:translateX(-50%);border:6px solid transparent;border-top-color:#1f2937;"></div>
</div>
</div>
const link = document.getElementById('tooltip-link');
const tooltip = document.getElementById('custom-tooltip');
link.addEventListener('mouseenter', () => {
tooltip.style.display = 'block';
});
link.addEventListener('mouseleave', () => {
tooltip.style.display = 'none';
});
// Alternative: Use data attributes
link.setAttribute('data-tooltip', 'Click to learn more');
Breadcrumb navigation Jump to this section
Generate breadcrumb links from URL path.
function generateBreadcrumbs(path) {
const container = document.getElementById('breadcrumbs');
const parts = path.split('/').filter(Boolean);
let currentPath = '';
const breadcrumbs = parts.map((part, index) => {
currentPath += '/' + part;
const isLast = index === parts.length - 1;
if (isLast) {
return `<span style="color:#6b7280;">${part}</span>`;
} else {
return `<a href="${currentPath}"
style="color:#3b82f6;text-decoration:none;">
${part}
</a>`;
}
});
container.innerHTML = breadcrumbs.join(' / ');
}
Download with progress Jump to this section
Show download progress for file links.
<a href="#" id="download-link">Download file</a>
<div id="download-progress" style="display:none;">
<div style="height:4px;background:#e5e7eb;border-radius:2px;overflow:hidden;">
<div id="progress-bar" style="height:100%;width:0%;background:#3b82f6;"></div>
</div>
<div id="progress-text">0%</div>
</div>
const downloadLink = document.getElementById('download-link');
const progressDiv = document.getElementById('download-progress');
const progressBar = document.getElementById('progress-bar');
const progressText = document.getElementById('progress-text');
downloadLink.addEventListener('click', async (e) => {
e.preventDefault();
progressDiv.style.display = 'block';
// Simulate download progress
for (let i = 0; i <= 100; i += 10) {
await new Promise(resolve => setTimeout(resolve, 200));
progressBar.style.width = i + '%';
progressText.textContent = i + '%';
}
progressText.textContent = 'Complete!';
setTimeout(() => {
progressDiv.style.display = 'none';
progressBar.style.width = '0%';
}, 2000);
});
