CSS Links - Link Styling
Links are the most basic element of the web. CSS gives you full control over how links look in various states — normal, visited, while hovered, while clicked, and while focused. A solid understanding of link pseudo-classes is essential for building interactive and accessible websites.
The correct order for link pseudo-classes is LVHA — Link, Visited, Hover, Active. Changing this order can cause styles to stop working correctly because of the CSS cascade.
In addition, :focus is very important for accessibility so keyboard users can see which element is currently active.
Code Example
Complete Link Styling
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>CSS Links</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Segoe UI', Tahoma, sans-serif;
padding: 30px;
background: #f0f2f5;
color: #334155;
}
h2 {
margin-bottom: 15px;
color: #1a1a2e;
}
.section {
margin-bottom: 40px;
background: white;
padding: 25px;
border-radius: 12px;
box-shadow: 0 2px 10px rgba(0,0,0,0.08);
}
.label {
font-size: 12px;
color: #64748b;
margin-bottom: 10px;
font-family: monospace;
background: #e2e8f0;
display: inline-block;
padding: 3px 8px;
border-radius: 4px;
margin-bottom: 15px;
}
/* ===== BASIC LINK STYLES (LVHA) ===== */
.basic-link {
color: #667eea;
text-decoration: none;
transition: color 0.3s;
}
.basic-link:link {
color: #667eea;
}
.basic-link:visited {
color: #764ba2;
}
.basic-link:hover {
color: #f5576c;
}
.basic-link:active {
color: #ff6b6b;
}
/* ===== UNDERLINE ON HOVER ===== */
.underline-link {
color: #1e293b;
text-decoration: none;
position: relative;
padding-bottom: 2px;
}
.underline-link::after {
content: '';
position: absolute;
bottom: 0;
left: 0;
width: 0;
height: 2px;
background: #667eea;
transition: width 0.3s;
}
.underline-link:hover::after {
width: 100%;
}
.underline-link:hover {
color: #667eea;
}
/* ===== BUTTON STYLE LINKS ===== */
.btn-link {
display: inline-block;
padding: 10px 24px;
background: #667eea;
color: white;
text-decoration: none;
border-radius: 8px;
font-weight: 600;
transition: all 0.3s;
}
.btn-link:hover {
background: #5a67d8;
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(102, 126, 234, 0.4);
}
.btn-link:active {
transform: translateY(0);
box-shadow: 0 2px 6px rgba(102, 126, 234, 0.3);
}
.btn-link:focus {
outline: 3px solid #c7d2fe;
outline-offset: 2px;
}
.btn-outline-link {
display: inline-block;
padding: 10px 24px;
background: transparent;
color: #667eea;
text-decoration: none;
border: 2px solid #667eea;
border-radius: 8px;
font-weight: 600;
transition: all 0.3s;
}
.btn-outline-link:hover {
background: #667eea;
color: white;
}
/* ===== FOCUS STATE (ACCESSIBILITY) ===== */
.accessible-link {
color: #667eea;
text-decoration: underline;
padding: 4px 8px;
border-radius: 4px;
transition: all 0.2s;
}
.accessible-link:focus {
outline: 3px solid #667eea;
outline-offset: 2px;
background: #eef2ff;
}
.accessible-link:focus:not(:focus-visible) {
outline: none;
background: none;
}
.accessible-link:focus-visible {
outline: 3px solid #667eea;
outline-offset: 2px;
background: #eef2ff;
}
/* ===== LINK GROUPS ===== */
.link-list {
list-style: none;
display: flex;
gap: 20px;
flex-wrap: wrap;
}
.link-list a {
color: #475569;
text-decoration: none;
padding: 8px 16px;
border-radius: 6px;
transition: all 0.3s;
}
.link-list a:hover {
background: #f1f5f9;
color: #667eea;
}
.link-list a.active {
background: #667eea;
color: white;
}
/* ===== NAVIGATION LINKS ===== */
.nav-demo {
display: flex;
gap: 5px;
background: #1a1a2e;
padding: 10px;
border-radius: 10px;
}
.nav-demo a {
color: #cbd5e1;
text-decoration: none;
padding: 10px 20px;
border-radius: 6px;
transition: all 0.3s;
font-weight: 500;
}
.nav-demo a:hover {
background: rgba(255,255,255,0.1);
color: white;
}
.nav-demo a.active {
background: #667eea;
color: white;
}
/* ===== BREADCRUMB ===== */
.breadcrumb {
display: flex;
align-items: center;
gap: 8px;
list-style: none;
font-size: 14px;
}
.breadcrumb a {
color: #667eea;
text-decoration: none;
transition: color 0.2s;
}
.breadcrumb a:hover {
color: #5a67d8;
text-decoration: underline;
}
.breadcrumb .separator {
color: #cbd5e1;
}
.breadcrumb .current {
color: #64748b;
pointer-events: none;
}
/* ===== FOOTER LINKS ===== */
.footer-links {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 30px;
background: #1e293b;
padding: 40px;
border-radius: 12px;
}
.footer-links h4 {
color: white;
margin-bottom: 15px;
font-size: 14px;
text-transform: uppercase;
letter-spacing: 0.5px;
}
.footer-links ul {
list-style: none;
}
.footer-links li {
margin-bottom: 10px;
}
.footer-links a {
color: #94a3b8;
text-decoration: none;
font-size: 14px;
transition: all 0.3s;
display: inline-block;
}
.footer-links a:hover {
color: #818cf8;
transform: translateX(4px);
}
/* ===== LINK ICON ===== */
.icon-link {
color: #667eea;
text-decoration: none;
display: inline-flex;
align-items: center;
gap: 6px;
font-weight: 600;
transition: gap 0.3s;
}
.icon-link:hover {
gap: 10px;
color: #5a67d8;
}
.icon-link::after {
content: '→';
}
.icon-link-back::after {
content: none;
}
.icon-link-back::before {
content: '←';
}
/* ===== BADGE LINK ===== */
.badge-link {
display: inline-flex;
align-items: center;
gap: 6px;
color: #475569;
text-decoration: none;
padding: 6px 14px;
background: #f1f5f9;
border-radius: 20px;
font-size: 14px;
transition: all 0.3s;
}
.badge-link:hover {
background: #667eea;
color: white;
}
.badge-link .count {
background: #667eea;
color: white;
padding: 2px 8px;
border-radius: 10px;
font-size: 12px;
font-weight: bold;
}
.badge-link:hover .count {
background: white;
color: #667eea;
}
.link-group {
display: flex;
flex-wrap: wrap;
gap: 10px;
margin-top: 15px;
}
.link-examples {
display: flex;
flex-direction: column;
gap: 15px;
margin-top: 15px;
}
</style>
</head>
<body>
<!-- Basic LVHA -->
<div class="section">
<h2>Basic Link — LVHA Order</h2>
<span class="label">:link → :visited → :hover → :active</span>
<p style="margin-bottom: 15px; color: #64748b;">
The order of pseudo-classes is <strong>very important</strong>. If the order is wrong, the styles will not work because of the CSS cascade.
</p>
<div class="link-examples">
<a href="#" class="basic-link">Normal Link (not visited)</a>
<a href="https://google.com" class="basic-link">Link Sudah Dikunjungi (visited)</a>
</div>
</div>
<!-- Underline Animation -->
<div class="section">
<h2>Underline Animation</h2>
<span class="label">::after pseudo-element + transition</span>
<div class="link-examples">
<a href="#" class="underline-link">Hover me for an underline animation</a>
<a href="#" class="underline-link">This animation uses the ::after pseudo-element</a>
<a href="#" class="underline-link">Width changes from 0 to 100%</a>
</div>
</div>
<!-- Button Style Links -->
<div class="section">
<h2>Button Style Links</h2>
<span class="label">display: inline-block + padding + border-radius</span>
<div class="link-group">
<a href="#" class="btn-link">Primary Button</a>
<a href="#" class="btn-outline-link">Outline Button</a>
</div>
</div>
<!-- Accessibility Focus -->
<div class="section">
<h2>Focus State (Accessibility)</h2>
<span class="label">:focus-visible { outline: 3px solid } </span>
<p style="margin-bottom: 15px; color: #64748b;">
Tab to this link to see the focus ring. Use <code>:focus-visible</code> only for the keyboard, not for mouse clicks.
</p>
<div class="link-examples">
<a href="#" class="accessible-link">Tab here to see the focus ring</a>
<a href="#" class="accessible-link">Second accessible link</a>
</div>
</div>
<!-- Navigation Links -->
<div class="section">
<h2>Navigation Links</h2>
<span class="label">Flexbox + active state</span>
<nav class="nav-demo">
<a href="#">Home</a>
<a href="#" class="active">Products</a>
<a href="#">Tentang</a>
<a href="#">Blog</a>
<a href="#">Kontak</a>
</nav>
</div>
<!-- Link Group -->
<div class="section">
<h2>Link Group</h2>
<span class="label">Flexbox wrap + hover background</span>
<div class="link-group">
<a href="#" class="badge-link">All <span class="count">124</span></a>
<a href="#" class="badge-link">Active <span class="count">89</span></a>
<a href="#" class="badge-link">Draft <span class="count">23</span></a>
<a href="#" class="badge-link">Arsip <span class="count">12</span></a>
</div>
</div>
<!-- Breadcrumb -->
<div class="section">
<h2>Breadcrumb Navigation</h2>
<span class="label">Flexbox + separator + current state</span>
<nav>
<ol class="breadcrumb">
<li><a href="#">Home</a></li>
<li class="separator">/</li>
<li><a href="#">Products</a></li>
<li class="separator">/</li>
<li><a href="#">Elektronik</a></li>
<li class="separator">/</li>
<li class="current">Laptop ASUS ROG</li>
</ol>
</nav>
</div>
<!-- Icon Links -->
<div class="section">
<h2>Icon Links</h2>
<span class="label">Inline-flex + ::after arrow</span>
<div class="link-examples">
<a href="#" class="icon-link">Read More</a>
<a href="#"="icon-link icon-link-back">Back</a>
<a href="#" class="icon-link">View All Products</a>
</div>
</div>
<!-- Footer Links -->
<div class="section" style="background: transparent; padding: 0; box-shadow: none;">
<h2 style="color: #1a1a2e;">Footer Links</h2>
<span class="label">Grid layout + hover translateX</span>
<div class="footer-links">
<div>
<h4>Products</h4>
<ul>
<li><a href="#">Feature</a></li>
<li><a href="#">Price</a></li>
<li><a href="#">Integrasi</a></li>
<li><a href="#">API</a></li>
</ul>
</div>
<div>
<h4>Perusahaan</h4>
<ul>
<li><a href="#">Tentang Kami</a></li>
<li><a href="#">Karir</a></li>
<li><a href="#">Blog</a></li>
<li><a href="#">Press</a></li>
</ul>
</div>
<div>
<h4>Dukungan</h4>
<ul>
<li><a href="#">Help Center</a></li>
<li><a href="#">Kontak</a></li>
<li><a href="#">Status</a></li>
<li><a href="#">Community</a</li>
</ul>
</div>
<div>
<h4>Legal</h4>
<ul>
<li><a href="#">Privacy Policy</a></li>
<li><a href="#">Terms of Service</a></li>
<li><a href="#">Cookie Policy</a></li>
</ul>
</div>
</div>
</div>
</body>
</html>
Code Explanation
LVHA Order
The correct pseudo-class order for links:
a:link { color: blue; } /* L - Link: not visited yet */
a:visited { color: purple; } /* V - Visited: already visited */
a:hover { color: red; } /* H - Hover: mouse over it */
a:active { color: orange; } /* A - Active: while being clicked */
Why LVHA? CSS uses the cascade. If :hover is written before :visited, then :visited will override :hover for links that have already been visited.
text-decoration on Links
/* Remove underline */
a { text-decoration: none; }
/* Add underline only on hover */
a:hover { text-decoration: underline; }
/* Thin, modern-style underline */
a {
text-decoration: none;
background-image: linear-gradient(currentColor, currentColor);
background-size: 0% 2px;
background-position: 0 100%;
background-repeat: no-repeat;
transition: background-size 0.3s;
}
a:hover { background-size: 100% 2px; }
Custom Link Styles
/* Link card style */
a.card-link {
display: block;
padding: 20px;
background: white;
border-radius: 8px;
text-decoration: none;
color: inherit;
transition: transform 0.3s, box-shadow 0.3s;
}
a.card-link:hover {
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(0,0,0,0.15);
}
/* Link gradient underline */
a.gradient-link {
text-decoration: none;
background: linear-gradient(90deg, #667eea, #764ba2);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
:focus for Accessibility
/* Focus ring for keyboard navigation */
a:focus-visible {
outline: 3px solid #667eea;
outline-offset: 2px;
}
/* Do not show the outline for mouse clicks */
a:focus:not(:focus-visible) {
outline: none;
}
:focus-visible is only active during keyboard navigation (Tab), not on mouse click. This is a best practice for accessibility.
Everyday Use Cases
1. Navigation Menu with Dropdown Indicators
<!DOCTYPE html>
<html lang="en">
<head>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
.top-nav {
display: flex;
align-items: center;
justify-content: space-between;
background: white;
padding: 15px 30px;
box-shadow: 0 2px 10px rgba(0,0,0,0.08);
}
.nav-brand {
font-size: 22px;
font-weight: bold;
color: #1a1a2e;
text-decoration: none;
}
.nav-menu {
display: flex;
list-style: none;
gap: 5px;
}
.nav-menu a {
text-decoration: none;
color: #475569;
padding: 10px 18px;
border-radius: 8px;
font-weight: 500;
transition: all 0.3s;
display: flex;
align-items: center;
gap: 6px;
}
.nav-menu a:hover {
background: #f1f5f9;
color: #667eea;
}
.nav-menu a.active {
background: #eef2ff;
color: #667eea;
}
.nav-menu a.has-dropdown::after {
content: '▾';
font-size: 10px;
}
.nav-actions {
display: flex;
gap: 10px;
align-items: center;
}
.nav-actions .link-login {
text-decoration: none;
color: #475569;
font-weight: 500;
padding: 8px 16px;
border-radius: 6px;
transition: background 0.3s;
}
.nav-actions .link-login:hover {
background: #f1f5f9;
}
.nav-actions .link-signup {
text-decoration: none;
color: white;
background: #667eea;
padding: 8px 20px;
border-radius: 6px;
font-weight: 600;
transition: background 0.3s;
}
.nav-actions .link-signup:hover {
background: #5a67d8;
}
</style>
</head>
<body>
<nav class="top-nav">
<a href="#" class="nav-brand">SkillVersitas</a>
<ul class="nav-menu">
<li><a href="#">Home</a></li>
<li><a href="#" class="active">Kursus</a></li>
<li><a href="#" class="has-dropdown">Kategori</a></li>
<li><a href="#">Mentor</a></li>
<li><a href="#">Komunitas</a></li>
</ul>
<div class="nav-actions">
<a href="#" class="link-login">Log In</a>
<a href="#" class="link-signup">Sign Up Free</a>
</div>
</nav>
</body>
</html>
2. Related Posts with Links
<!DOCTYPE html>
<html lang="en">
<head>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
.related-section {
padding: 40px 20px;
max-width: 800px;
margin: 0 auto;
}
.related-section h2 {
margin-bottom: 25px;
color: #1a1a2e;
}
.related-list {
display: flex;
flex-direction: column;
gap: 15px;
}
.related-item {
display: flex;
gap: 20px;
padding: 20px;
background: white;
border-radius: 12px;
box-shadow: 0 2px 8px rgba(0,0,0,0.06);
text-decoration: none;
color: inherit;
transition: all 0.3s;
border: 2px solid transparent;
}
.related-item:hover {
border-color: #667eea;
transform: translateX(5px);
box-shadow: 0 4px 15px rgba(102, 126, 234, 0.15);
}
.related-thumb {
width: 100px;
height: 80px;
border-radius: 8px;
flex-shrink: 0;
display: flex;
align-items: center;
justify-content: center;
color: white;
font-weight: bold;
}
.related-thumb:nth-child(1) { background: #667eea; }
.related-item:nth-child(1) .related-thumb { background: #667eea; }
.related-item:nth-child(2) .related-thumb { background: #f5576c; }
.related-item:nth-child(3) .related-thumb { background: #43e97b; }
.related-content h3 {
font-size: 16px;
margin-bottom: 6px;
color: #1e293b;
transition: color 0.3s;
}
.related-item:hover .related-content h3 {
color: #667eea;
}
.related-content p {
font-size: 14px;
color: #64748b;
line-height: 1.5;
}
.related-meta {
font-size: 12px;
color: #94a3b8;
margin-top: 8px;
}
.read-more {
display: inline-flex;
align-items: center;
gap: 6px;
color: #667eea;
text-decoration: none;
font-weight: 600;
font-size: 14px;
margin-top: 10px;
transition: gap 0.3s;
}
.read-more:hover {
gap: 10px;
}
.read-more::after {
content: '→';
}
</style>
</head>
<body>
<section class="related-section">
<h2>Related Articles</h2>
<div class="related-list">
<a href="#" class="related-item">
<div class="related-thumb">1</div>
<div class="related-content">
<h3>Understanding CSS Flexbox from the Basics</h3>
<p>A complete guide to understanding Flexbox for beginners, with real-world case studies.</p>
<span class="read-more">Read More</span>
</div>
</a>
<a href="#" class="related-item">
<div class="related-thumb">2</div>
<div class="related-content">
<h3>CSS Grid vs Flexbox: Which One to Choose?</h3>
<p>An in-depth comparison of when to use Grid and when to use Flexbox.</p>
<span class="read-more">Read More</span>
</div>
</a>
<a href="#" class="related-item">
<div class="related-thumb">3</div>
<div class="related-content">
<h3>Responsive Design Modern Without Media Queries</h3>
<p>Techniques using minmax(), auto-fit, and the fr unit for responsive layouts.</p>
<span class="read-more">Read More</span>
</div>
</a>
</div>
</section>
</body>
</html>
3. Social Links
<!DOCTYPE html>
<html lang="en">
<head>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
.social-section {
display: flex;
flex-direction: column;
align-items: center;
gap: 20px;
padding: 40px;
}
.social-links {
display: flex;
gap: 15px;
}
.social-link {
display: flex;
align-items: center;
justify-content: center;
width: 50px;
height: 50px;
border-radius: 50%;
text-decoration: none;
color: white;
font-weight: bold;
font-size: 18px;
transition: all 0.3s;
position: relative;
}
.social-link:hover {
transform: translateY(-3px);
box-shadow: 0 5px 15px rgba(0,0,0,0.2);
}
.social-link:focus-visible {
outline: 3px solid #667eea;
outline-offset: 3px;
}
.social-link.twitter { background: #1da1f2; }
.social-link.github { background: #333; }
.social-link.linkedin { background: #0a66c2; }
.social-link.youtube { background: #ff0000; }
.social-link.github::before { content: 'GH'; }
.social-link.twitter::before { content: 'TW'; }
.social-link.linkedin::before { content: 'IN'; }
.social-link.youtube::before { content: 'YT'; }
.share-links {
display: flex;
gap: 10px;
}
.share-link {
display: inline-flex;
align-items: center;
gap: 6px;
padding: 8px 16px;
border-radius: 20px;
text-decoration: none;
font-size: 13px;
font-weight: 600;
transition: all 0.3s;
}
.share-link.twitter {
background: #e8f5fe;
color: #1da1f2;
}
.share-link.twitter:hover {
background: #1da1f2;
color: white;
}
.share-link.facebook {
background: #e7f3ff;
color: #1877f2;
}
.share-link.facebook:hover {
background: #1877f2;
color: white;
}
.share-link.whatsapp {
background: #e6faf0;
color: #25d366;
}
.share-link.whatsapp:hover {
background: #25d366;
color: white;
}
</style>
</head>
<body>
<div class="social-section">
<h2>Ikuti Kami</h2>
<div class="social-links">
<a href="#" class="social-link github" aria-label="GitHub"></a>
<a href="#" class="social-link twitter" aria-label="Twitter"></a>
<a href="#" class="social-link linkedin" aria-label="LinkedIn"></a>
<a href="#" class="social-link youtube" aria-label="YouTube"></a>
</div>
<h3 style="margin-top: 20px; font-size: 16px; color: #64748b;">Share This Article</h3>
<div class="share-links">
<a href="#" class="share-link twitter">🐦 Twitter</a>
<a href="#" class="share-link facebook">📘 Facebook</a>
<a href="#" class="share-link whatsapp">💬 WhatsApp</a>
</div>
</div>
</body>
</html>
Conclusion
CSS Links lets you create interactive and accessible links. Key points:
- LVHA order —
:link,:visited,:hover,:active— the correct order is crucial :focus-visible— Accessibility best practice for keyboard navigationtext-decoration: none— Remove the default underline and create a custom underline with a pseudo-element- Transform & Transition — Smooth hover effects on links
- Semantic HTML — Use
<nav>for navigation and<a>for all links
Always test your links with the keyboard (Tab) to ensure accessibility. A focus ring must not be removed without providing a visual alternative.