Links, Buttons, and Navigation Styling
Introduction
Links, buttons, and navigation controls are the core interaction layer of most websites. If these elements look unclear or behave inconsistently, users get lost quickly. This chapter covers practical styling patterns for interactive controls with strong focus on clarity, state feedback, and accessibility.
Prerequisites
- Basic pseudo-classes (
:hover,:focus-visible,:active) - Basic spacing and typography styling
- Familiarity with responsive layout fundamentals
Link vs Button: Semantic First
Before styling, keep semantics correct:
- use
<a>for navigation to another URL/location - use
<button>for in-page actions (toggle, submit, open modal)
Styling can make them look similar, but behavior and accessibility expectations differ.
Styling Text Links
A good baseline:
Code explanation:
- underline preserves link discoverability in content text
- hover and focus-visible provide clear interaction feedback
- keyboard users get visible focus ring
Avoid removing underlines globally unless you provide equally clear alternatives.
Visited and External Link Cues
a:visited {
color: #7c3aed;
}
a[target="_blank"]::after {
content: " ↗";
font-size: 0.9em;
}This can help users understand browsing history and external navigation behavior.
Use subtle cues; avoid visual clutter in dense text blocks.
Button Baseline Style
Code explanation:
inline-flexaligns icon + label cleanlymin-height: 44pximproves touch usabilitycursor: pointerclarifies clickability- transition supports smooth state changes
Button Interaction States
Use distinct visual states for hover, active, focus, and disabled to avoid ambiguity.
Button Variants
Example variant system:
Keep variant count small and purposeful for consistent UX.
Navigation Container Basics
Simple horizontal nav:
.nav {
display: flex;
align-items: center;
gap: 0.75rem;
}Responsive baseline:
@media (max-width: 700px) {
.nav {
flex-wrap: wrap;
}
}For more advanced responsive nav patterns, pair with disclosure toggles and clear focus order.
Navigation Link Styling
Padding makes click targets easier to use than plain text-only links.
Active Navigation State
You can mark current page with aria-current="page":
.nav a[aria-current="page"] {
background: #dbeafe;
color: #1e3a8a;
font-weight: 600;
}This is more robust than relying on color-only hover behavior.
Skip Link Pattern
Accessibility-friendly top skip link:
This helps keyboard users jump directly to main content.
Focus Visibility and Contrast Rules
Interaction styling should always preserve:
- visible keyboard focus
- readable text/background contrast
- clear affordance difference between normal and interactive elements
Do not style links/buttons to look like plain body text without extra cues.
Warning
Do Not Remove Focus Ring Globally
If default focus styles are removed, replace them immediately with strong custom :focus-visible styles.
Responsive Navigation Considerations
On narrow screens:
- increase tap target size
- avoid crowded horizontal menus
- keep primary actions visible
- ensure menu toggles are keyboard accessible
Even simple wrap behavior can be better than forcing tiny unreadable nav text.
Common Mistakes
| Mistake | Why it hurts | Better approach |
|---|---|---|
Styling <a> and <button> interchangeably without semantics | Accessibility/behavior mismatch | Use correct element semantics first |
| Removing underlines from all links | Reduced discoverability | Keep underlines in content text |
| No focus-visible styles | Keyboard navigation becomes unclear | Add clear focus ring for interactive controls |
| Tiny click targets | Hard mobile interaction | Keep comfortable padding/min-height |
| Disabled state only by color change | Ambiguous and inaccessible | Combine opacity/cursor/state semantics |
Debugging Interaction Styles
When controls feel inconsistent:
- verify semantic element choice (
avsbutton) - force states in DevTools (
:hover,:active,:focus-visible) - check specificity/order conflicts in state styles
- test keyboard tab sequence and visibility
- test touch interaction on real mobile device
State testing should be part of every UI review.
Mini Exercise
- Build a nav bar with 4 links and one primary action button
- Add hover + focus-visible states for all interactive items
- Mark one nav link with
aria-current="page"and style it - Add a skip link to main content
- Verify keyboard-only navigation from top to bottom
FAQ
Can I style a link to look like a button?
Yes, if it still performs navigation. Keep semantic element correct and preserve focus/interaction cues.
Should link underlines always stay visible?
In body text, usually yes. In nav bars/buttons, alternative strong cues can be acceptable.
Why use aria-current="page" in nav?
It helps assistive technologies identify current location and allows robust active-state styling.
Is :focus-visible enough by itself?
For most modern browsers, yes for interactive focus styling. Consider fallback strategy if your support matrix requires it.
What is the best minimum touch target size?
A common practical target is around 44px in at least one dimension for comfortable tap interaction.