How do you build animated menus that stay accessible?
Navigation effects make menus, tabs and tooltips easier to follow: underlines that slide to the active link, hamburgers that morph into a close icon, dropdowns and accordions that expand smoothly. They use CSS transitions, the details element or small scripts, and CSS anchor positioning, where supported, to attach tooltips to their trigger.
How to choose, performance and accessibility
- Underline Expand and Pill Indicator suit a site header, Morphing Hamburger a mobile menu, Tab Slider a pricing or feature switcher, and Sticky Header Detection a long page.
- Every menu must open, close with Escape and move focus correctly from the keyboard, expose its state with
aria-expanded, and remain usable without animation. - Underline Expand, Accordion Basic, Smart Tooltip System and Connected Nodes are free with their full code; the other navigation components come with Premium.
View source code
<div class="demo-preview">
<div class="nav-demo">
<span class="nav-link-demo link-underline-expand">Home</span>
<span class="nav-link-demo link-underline-expand">Services</span>
<span class="nav-link-demo link-underline-expand">Contact</span>
</div>
</div>.demo-preview,
.demo-preview *,
.demo-preview *::before,
.demo-preview *::after {
box-sizing: border-box
}
.demo-preview {
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 250px;
overflow: hidden;
position: relative;
background: rgb(26, 26, 36);
color: rgb(255, 255, 255);
font-family: sans-serif;
}
/* Variables du design system du site, dont ce code dépend (valeurs de css/style.css — à adapter librement). */
.demo-preview {
--gradient-primary: linear-gradient(135deg, #6366f1 0%, #8b5cf6 50%, #d946ef 100%);
--space-2: 0.5rem;
--space-8: 2rem;
--text-primary: #ffffff;
--text-secondary: #a1a1aa;
}
.nav-demo {
display: flex;
gap: var(--space-8);
align-items: center;
}
.nav-link-demo {
color: var(--text-secondary);
font-weight: 500;
padding: var(--space-2) 0;
position: relative;
cursor: pointer;
transition: color 0.3s;
}
.nav-link-demo:hover {
color: var(--text-primary);
}
.link-underline-expand::after {
content: '';
position: absolute;
bottom: 0;
left: 50%;
width: 0;
height: 2px;
background: var(--gradient-primary);
transition: all 0.3s ease;
transform: translateX(-50%);
}
.link-underline-expand:hover::after {
width: 100%;
}/* Pure CSS — no JavaScript required */Sticky Header Detection
Sticky header with Intersection Observer that detects scroll and changes style.
Effect page →Custom Bezier Transition
Color transition with custom cubic-bezier curve for smooth movement.
Effect page →Floating Indicator
Floating indicator with smooth cubic-bezier transition. Inspired by CTA Gallery.
Effect page →Accordion Basic
Expandable sections with smooth height animation. Multiple sections can be open.
Effect page →View source code
<div class="demo-preview">
<div class="component-demo">
<div class="accordion" id="accordionBasic">
<div class="accordion-item active">
<button class="accordion-header" onclick="toggleAccordion(this, 'basic')">
Section 1
<svg class="accordion-icon" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M6 9l6 6 6-6"/>
</svg>
</button>
<div class="accordion-content">
<div class="accordion-body">
Content of the first section with smooth height animation.
</div>
</div>
</div>
<div class="accordion-item">
<button class="accordion-header" onclick="toggleAccordion(this, 'basic')">
Section 2
<svg class="accordion-icon" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M6 9l6 6 6-6"/>
</svg>
</button>
<div class="accordion-content">
<div class="accordion-body">
Second section with different content.
</div>
</div>
</div>
<div class="accordion-item">
<button class="accordion-header" onclick="toggleAccordion(this, 'basic')">
Section 3
<svg class="accordion-icon" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M6 9l6 6 6-6"/>
</svg>
</button>
<div class="accordion-content">
<div class="accordion-body">
Third and final section.
</div>
</div>
</div>
</div>
</div>
</div>.demo-preview,
.demo-preview *,
.demo-preview *::before,
.demo-preview *::after {
box-sizing: border-box
}
.demo-preview {
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 250px;
overflow: hidden;
position: relative;
background: rgb(26, 26, 36);
color: rgb(255, 255, 255);
font-family: sans-serif;
}
.component-demo {
width: 100%;
min-height: 200px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 12px;
}
.accordion {
width: 100%;
max-width: 350px;
}
.accordion-item {
background: rgba(255, 255, 255, 0.05);
border-radius: 8px;
margin-bottom: 8px;
overflow: hidden;
}
.accordion-header {
width: 100%;
padding: 16px 20px;
background: transparent;
border: none;
color: white;
font-size: 0.95rem;
font-weight: 500;
font-family: inherit;
display: flex;
justify-content: space-between;
align-items: center;
cursor: pointer;
transition: background 0.3s ease;
}
.accordion-header:hover {
background: rgba(255, 255, 255, 0.05);
}
.accordion-icon {
transition: transform 0.3s ease;
}
.accordion-item.active .accordion-icon {
transform: rotate(180deg);
}
.accordion-content {
max-height: 0;
overflow: hidden;
transition: max-height 0.4s ease, padding 0.3s ease;
}
.accordion-item.active .accordion-content {
max-height: 200px;
}
.accordion-body {
padding: 0 20px 16px;
color: rgba(255, 255, 255, 0.6);
font-size: 0.9rem;
line-height: 1.6;
}(function() {
function toggleAccordion(header, type) {
const item = header.parentElement;
const accordion = item.parentElement;
if (type === 'single') {
// Close all other items in single mode
accordion.querySelectorAll('.accordion-item').forEach(otherItem => {
if (otherItem !== item) {
otherItem.classList.remove('active');
}
});
}
item.classList.toggle('active');
}
window.toggleAccordion = toggleAccordion;
})();Toast Success
Green success notification with slide animation. Disappears after 3 seconds.
Effect page →