Neumorphic Pill Navigation
A smooth pill-style navigation menu with a raised active tab, subtle neumorphic hover effects and responsive behavior.
<div class="cr-pill-nav">
<button class="cr-pill-item active" type="button">
Home
</button>
<button class="cr-pill-item" type="button">
About
</button>
<button class="cr-pill-item" type="button">
Portfolio
</button>
<button class="cr-pill-item" type="button">
Contact
</button>
</div>
.cr-pill-nav{
display:flex;
align-items:center;
gap:0;
width:max-content;
padding:7px;
background:#08111f;
border:1px solid rgba(34,211,238,.14);
border-radius:999px;
box-shadow:
0 10px 24px rgba(0,0,0,.38),
inset 0 1px 0 rgba(255,255,255,.03),
inset 0 -2px 4px rgba(0,0,0,.28);
}
.cr-pill-item{
min-width:105px;
height:52px;
padding:0 24px;
border:0;
border-radius:999px;
background:transparent;
color:#8090a7;
font-family:Inter,Arial,sans-serif;
font-size:15px;
font-weight:600;
cursor:pointer;
transition:
color .25s ease,
background .25s ease,
box-shadow .25s ease,
transform .25s ease;
}
.cr-pill-item:hover{
color:#dbeafe;
background:#0a1424;
box-shadow:
inset 3px 3px 7px rgba(0,0,0,.48),
inset -2px -2px 5px rgba(255,255,255,.025);
}
.cr-pill-item.active{
color:#ffffff;
background:
linear-gradient(
90deg,
#06b6d4 0%,
#2563eb 48%,
#7c3aed 100%
);
box-shadow:
0 7px 18px rgba(37,99,235,.22),
0 0 16px rgba(124,58,237,.10),
inset 0 1px 0 rgba(255,255,255,.18);
transform:translateY(-2px);
}
.cr-pill-item.active:hover{
color:#ffffff;
background:
linear-gradient(
90deg,
#06b6d4 0%,
#2563eb 48%,
#7c3aed 100%
);
box-shadow:
0 7px 18px rgba(37,99,235,.22),
0 0 16px rgba(124,58,237,.10),
inset 0 1px 0 rgba(255,255,255,.18);
}
@media(max-width:600px){
.cr-pill-nav{
width:100%;
max-width:420px;
padding:5px;
}
.cr-pill-item{
flex:1;
min-width:0;
height:46px;
padding:0 10px;
font-size:13px;
}
}
const pillNav = document.querySelector('.cr-pill-nav');
if (pillNav) {
pillNav.addEventListener('click', function (e) {
const item = e.target.closest('.cr-pill-item');
if (!item) return;
pillNav
.querySelectorAll('.cr-pill-item')
.forEach(function (button) {
button.classList.remove('active');
});
item.classList.add('active');
});
}
How This Neumorphic Pill Navigation Works
The Neumorphic Pill Navigation is a compact horizontal navigation control built from four buttons: Home, About, Portfolio, and Contact. The entire component sits inside .cr-pill-nav, while each navigation option uses the shared .cr-pill-item class. Home starts with the active class, so it appears selected when the component first loads.
The outer navigation container uses Flexbox to keep all four buttons in a single row. Its width: max-content makes the container only as wide as its contents on larger screens. A 7px inner padding provides space around the buttons, while border-radius: 999px creates the fully rounded pill shape.
The dark neumorphic appearance comes mainly from the background, border, and layered shadows. The container uses a #08111f background with a subtle cyan-tinted border. Its box-shadow combines a dark external shadow with two inset shadows. The external 0 10px 24px rgba(0,0,0,.38) shadow lifts the control from its surroundings, while the inset highlights and shadows add depth along the inner edges.
Each navigation button has a minimum width of 105px and a height of 52px. The buttons are transparent by default, with muted #8090a7 text and the same 999px border radius as the parent. This keeps every option visually consistent with the pill-shaped container.
Hovering over an inactive button changes its text to the lighter #dbeafe and gives it a #0a1424 background. Two inset shadows are then applied from opposite directions. This creates a pressed or recessed appearance rather than simply changing the background color.
The active state takes a different approach. Instead of looking recessed, the selected button receives a horizontal gradient running from cyan #06b6d4 through blue #2563eb to purple #7c3aed. It also receives external blue and purple shadows plus a subtle inset highlight. A translateY(-2px) transform raises the active item slightly above the other buttons. The active hover rule preserves these same colors and shadows rather than applying the recessed inactive hover effect.
All state changes use .25s CSS transitions. Color, background, box-shadow, and transform are animated, allowing the selected and hovered states to change gradually. For more information about the layout used to align the navigation buttons, see the MDN CSS flexible box layout documentation.
JavaScript controls which button is selected. Rather than attaching a separate event listener to every button, the script attaches one click listener to .cr-pill-nav. It then uses e.target.closest('.cr-pill-item') to determine whether the click occurred on a navigation item. If it did, the script removes active from every .cr-pill-item and applies it to the clicked button.
The component also includes a media query for screens up to 600px wide. At that size, the container changes to width: 100% with a maximum width of 420px. Each button receives flex: 1 and min-width: 0, allowing all four items to share the available width equally. Button height drops from 52px to 46px, horizontal padding becomes 10px, and the font size decreases from 15px to 13px.
Customizing the Neumorphic Pill Navigation
The existing CSS provides several straightforward values that can be changed to fit the component into a different interface.
- Change the Home, About, Portfolio, and Contact button text to match your navigation sections.
- Adjust the
105pxminimum width and52pxheight to change the desktop button dimensions. - Modify
#08111fand#0a1424to create a lighter or darker neumorphic surface. - Replace
#06b6d4,#2563eb, and#7c3aedto create a different active-button gradient. - Adjust the inset
box-shadowvalues to make the recessed hover state more or less pronounced. - Change
translateY(-2px)to control how far the selected button rises. - Modify the
.25stransitions to make state changes faster or slower. - Adjust the 600px breakpoint, 420px maximum width, or mobile button dimensions for another responsive layout.
Where to Use This Neumorphic Pill Navigation
This component works well when a small number of equally important sections need a compact horizontal selector.
- Portfolio page navigation
- Personal website section controls
- Dashboard view selectors
- Settings and preference sections
- Category or content filters
- Compact application navigation
Because the current JavaScript only changes the active visual state, actual page navigation or content switching would need to be handled separately. For an alternative that opens a larger list of navigation options, the Animated Fly-In Navigation Menu uses a sliding panel with staggered menu-item transitions.
Frequently Asked Questions
Does the Neumorphic Pill Navigation use JavaScript?
Yes. JavaScript detects clicks inside the navigation container, removes the existing active class, and assigns it to the button that was clicked.
Does clicking a button navigate to another page?
No. The current HTML uses button elements rather than links, and the JavaScript only updates the active state. There is no page-navigation behavior in the component.
How is the neumorphic effect created?
The effect comes primarily from layered box-shadow values. The outer container combines external and inset shadows, while inactive hovered buttons use opposing inset shadows to create a recessed appearance.
Is the Neumorphic Pill Navigation responsive?
Yes. Below 600px, the navigation can fill the available width up to 420px. The four buttons use flex: 1, smaller dimensions, and a 13px font size so they can fit more comfortably on narrow screens.
The Neumorphic Pill Navigation combines rounded surfaces, layered shadows, a gradient active state, responsive Flexbox sizing, and a small event-delegation script to provide a clear four-option navigation control.
