React Router: Active Navigation Links with NavLink and Styling
Navigation is central to any multi-page application. The <NavLink> component from React Router extends the basic <Link> by automatically adding an active class when its path matches the current URL. This enables you to highlight the current page in your navigation menu — a critical UX feature that tells users where they are. This article walks through building a complete navigation menu with active link styling, visual feedback, and best practices for modern routing.
Key Takeaways
<NavLink>is route-aware — unlike<Link>, it automatically detects when its path matches the current route and applies anactiveclass.- Active class is applied automatically — when a
<NavLink>path matches the current URL, React Router adds theactiveclass to the element, allowing CSS to style it differently. - Styling active links — use CSS to target the
.activeclass: change text color, font weight, add a background color, border, or any visual indication of the current page. - Current best practice — use the
classNameprop as a function to conditionally apply classes based onisActivestatus (v6+ syntax) for more control. - Navigation menu pattern — wrap
<NavLink>elements in a<nav>element and semantically use<ul>/<li>for accessible, maintainable menus.
What Is the Difference Between <Link> and <NavLink>?
Both <Link> and <NavLink> navigate to a new route without a full page reload. The key difference: <NavLink> is aware of the current route.
<Link>— basic client-side navigation. Does not know or care about the current route.<NavLink>— knows the current route and automatically applies theactiveclass when itstoprop matches the URL.
import { Link, NavLink } from 'react-router-dom';
// Link: no indication of active state
<Link to="/about">About</Link>
// NavLink: automatically gets .active class when route is /about
<NavLink to="/about">About</NavLink>
When the user visits /about, React Router automatically adds the active class to the <NavLink to="/about"> element. You then use CSS to style it.
How Do You Create a Navigation Menu with NavLink?
Building a navigation menu involves three steps: creating the <NavLink> components, styling them with CSS, and integrating the menu into your app.
Step 1: Create a Navbar Component
import React from 'react';
import { NavLink } from 'react-router-dom';
import './Navbar.css';
function Navbar() {
return (
<nav className="navbar">
<ul className="nav-links">
<li>
<NavLink to="/">Home</NavLink>
</li>
<li>
<NavLink to="/about">About</NavLink>
</li>
<li>
<NavLink to="/services">Services</NavLink>
</li>
<li>
<NavLink to="/contact">Contact</NavLink>
</li>
</ul>
</nav>
);
}
export default Navbar;
Use semantic HTML: wrap links in a <nav> element, and structure the list with <ul> and <li> for accessibility. Each <NavLink to="/path"> creates a link that becomes active when the URL matches /path.
Step 2: Style the Navigation Menu and Active Links
/* Navbar.css */
nav.navbar {
background-color: #f8f9fa;
padding: 1rem 2rem;
border-bottom: 1px solid #dee2e6;
}
.nav-links {
list-style: none;
display: flex;
gap: 2rem;
margin: 0;
padding: 0;
}
nav a {
text-decoration: none;
color: #333;
font-weight: 500;
padding: 0.5rem 1rem;
border-radius: 4px;
transition: all 0.3s ease;
}
/* Style the active link */
nav a.active {
color: #007bff;
font-weight: 700;
background-color: #e7f3ff;
border-left: 3px solid #007bff;
}
/* Hover effect for non-active links */
nav a:not(.active):hover {
color: #0056b3;
background-color: #f0f0f0;
}
The .active selector targets the link when its class is active. This allows visual differentiation: change text color, add a background color, add a border, increase font weight, or all of the above.
Step 3: Integrate the Navbar into Your App
import React from 'react';
import { Routes, Route } from 'react-router-dom';
import Navbar from './components/Navbar';
import Home from './pages/Home';
import About from './pages/About';
import Services from './pages/Services';
import Contact from './pages/Contact';
function App() {
return (
<div>
<Navbar />
<main>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="/services" element={<Services />} />
<Route path="/contact" element={<Contact />} />
</Routes>
</main>
</div>
);
}
export default App;
Place the <Navbar> component above the <Routes> so it appears on every page. When the user navigates, the matching <NavLink> automatically becomes active, and CSS styles it.
How Do You Control Active Link Styling with the className Prop?
React Router v6 provides a more flexible syntax: pass a function to className that receives an { isActive } object, allowing you to conditionally apply classes or inline styles.
import { NavLink } from 'react-router-dom';
function Navbar() {
return (
<nav>
<NavLink
to="/about"
className={({ isActive }) => isActive ? 'nav-link active' : 'nav-link'}
>
About
</NavLink>
</nav>
);
}
Or use a helper function for cleaner syntax:
const getLinkClass = ({ isActive }) =>
isActive ? 'nav-link nav-link--active' : 'nav-link';
<NavLink to="/about" className={getLinkClass}>
About
</NavLink>
This gives you full control: you can add multiple classes, apply inline styles, or even swap entire components based on whether the link is active.
What Are Common Active Link Styling Patterns?
Underline Indicator
nav a {
position: relative;
text-decoration: none;
}
nav a.active::after {
content: '';
position: absolute;
bottom: -4px;
left: 0;
width: 100%;
height: 2px;
background-color: #007bff;
}
Left Border Accent
nav a.active {
border-left: 3px solid #007bff;
padding-left: calc(1rem - 3px);
}
Badge or Pill Style
nav a.active {
background-color: #007bff;
color: white;
border-radius: 20px;
padding: 0.5rem 1rem;
}
Subtle Background Highlight
nav a.active {
background-color: #f0f0f0;
font-weight: 600;
}
Choose a pattern that fits your design. The key is clarity: users must immediately see which page they are on.
What Are Best Practices for Navigation Menus?
Use Semantic HTML
<nav> {/* <nav> landmark region */}
<ul> {/* List of links */}
<li>
<NavLink to="/">Home</NavLink>
</li>
</ul>
</nav>
Screen readers and accessibility tools understand this structure. Never use <div> instead of <nav>.
Nest Links in List Items
Wrapping each <NavLink> in an <li> improves semantics and makes CSS styling (like spacing between items) cleaner.
Ensure Sufficient Link Target Size
Make links at least 44×44 CSS pixels for touch accessibility:
nav a {
display: inline-block;
padding: 0.75rem 1rem; /* Ensures adequate clickable area */
min-height: 44px;
display: flex;
align-items: center;
}
Test Active State on All Pages
Verify the active styling appears correctly on every route. A common bug: the NavLink path is /about but the route is /About (case-sensitive).
Frequently Asked Questions
Why is my NavLink not showing as active?
Check that the to prop exactly matches the route path. React Router is case-sensitive. /about and /About are different.
// Route definition
<Route path="/about" element={<About />} />
// NavLink (must match exactly)
<NavLink to="/about">About</NavLink>
Can I style the active link with inline styles instead of CSS?
Yes, use the className function syntax:
<NavLink
to="/about"
style={({ isActive }) => ({
color: isActive ? '#007bff' : '#333',
fontWeight: isActive ? 'bold' : 'normal',
})}
>
About
</NavLink>
However, CSS classes are usually cleaner and more maintainable.
How do I style a partial match (e.g., all /admin/* routes)?
Use the end prop. By default, /admin is active for both /admin and /admin/users. Add end to match only exact paths:
<NavLink to="/admin" end>Admin</NavLink> {/* Active only at /admin */}
<NavLink to="/admin">Admin</NavLink> {/* Active at /admin and /admin/* */}
Should I use <NavLink> for all links or only navigation menus?
Use <NavLink> in navigation menus where showing the current page is important. Use <Link> for contextual links in page content (like "Read more" or inline references), where active state is not relevant.
Can I apply active styling to parent links in nested routes?
Use the className function to check if any child route is active:
const isAdminActive = ({ isActive }) =>
isActive || location.pathname.startsWith('/admin');
<NavLink to="/admin" className={isAdminActive ? 'active' : ''}>
Admin
</NavLink>
Or use React Router's useResolvedPath and useLocation hooks for more control.