How to Build an Animated Navigation Bar

Khadijah Maulion Masorong·September 26, 2026
How to Build an Animated Navigation Bar in WordPress — animated navbar
Udemy US - CPS

Search for "animated navbar" and you’ll find plenty of galleries. They’re satisfying to scroll through, but they leave you exactly where you started: staring at your header.php file with no idea how to make anything move. Building a working animated navbar means planning your triggers, choosing lightweight animation formats like Lottie, wiring up your WordPress files correctly, and testing for performance and accessibility before you ship it.

Capcut

This walkthrough covers the exact process I use when clients ask me to make their navigation "feel alive." It includes the code, the file locations, and the mistakes I’ve learned to avoid.

What You’ll Need Before Starting

Get these five things in place first. Skipping this step is the number one reason DIY navbar animations fail partway through.

  • Theme access. A child theme or custom theme you control. Editing a parent theme directly means updates will overwrite your changes. If you’re unsure about your theme structure, the article on building a WordPress theme from scratch walks through the file architecture.
  • A code editor. Visual Studio Code, Sublime Text, or any editor with syntax highlighting for PHP, HTML, CSS, and JavaScript.
  • Basic HTML, CSS, and JavaScript familiarity. You don’t need to be a senior developer, just comfortable reading a <div> tag and knowing what a CSS class does.
  • A Lottie JSON animation file. Either exported from Adobe After Effects using the Bodymovin plugin, or downloaded from LottieFiles, which is maintained by Airbnb’s design team.
  • A local or staging environment. Use LocalWP or a staging subdomain so you can test safely before touching your live site.

If any of these feel unfamiliar, it’s worth reading what Lottie animation is first, since the rest assumes you know the basic concept.

Step 1: Plan the Navbar Structure and Animation Triggers

Every animated navbar starts as a static one. Before writing animation code, sketch out what stays fixed – the logo and primary links – and what reacts to user behavior: the hamburger icon, active-link indicator, and background opacity on scroll.

Sketch the Navbar Layout

On paper or in a wireframe tool, lay out three zones: the logo on the left, primary navigation links in the center or right, and a mobile hamburger trigger below your chosen breakpoint. Deciding this now saves you from restructuring HTML markup later, after your JavaScript is already wired to specific class names.

Choose Your Trigger Type

This decision determines how much JavaScript you’ll need to write, but most tutorials skip it entirely. A hover trigger fires a CSS transition when the mouse enters an element. A scroll trigger fires a JavaScript event listener tied to window scroll position. A click trigger toggles a state, usually for opening a mobile menu.

Trigger Type Best Use Case Complexity Works Without JavaScript?
Hover Desktop dropdowns, link underlines, icon interactions Low Yes, pure CSS
Scroll Shrinking header, background changes, reveal animations Medium No, needs scroll listener
Click Mobile menu, expanding search, mega menu toggle Medium Partial, needs JS for state

For a small business site, start with hover and click triggers only. Add scroll-based animation once the rest is stable, since scroll listeners are the most common source of performance issues on lower-powered devices.

Step 2: Export and Prepare Your Lottie Animation File

Lottie renders vector animations from a JSON file instead of a video or GIF. This keeps file sizes tiny and keeps the animation sharp at any screen size. That’s why it beats a CSS-only effect for anything more complex than a color fade: you get designer-made motion at a fraction of the weight of an MP4.

Exporting JSON from After Effects and Bodymovin

Design your navbar icon or logo animation in Adobe After Effects, then export it using the free Bodymovin plugin, which converts the composition into JSON that any Lottie player can read. Keep your After Effects composition simple: solid shapes and shape layers export cleanly. Embedded raster images, blur effects, and expressions referencing 3D layers often break during export and need to be simplified or rebuilt as vector paths.

Optimizing File Size for Web Performance

A navbar animation should be small. I keep navbar-specific Lottie files under 50KB by reducing keyframe density, avoiding embedded images, and trimming unused layers before export. LottieFiles’ editor lets you preview and compress the file in the browser before you ever touch WordPress. If your exported JSON exceeds 200KB for a simple navbar icon, something in the composition is more complex than it needs to be – usually a raster image that should have been rebuilt as a vector shape.

Step 3: Set Up the Theme Files and Enqueue Scripts

This is the step every gallery and component library page skips, and it’s what actually matters if you’re running WordPress.

Locating header.php and functions.php

Your navigation markup almost always lives inside header.php, either directly or inside a template part like template-parts/navigation.php. Your script and style loading logic lives in functions.php. If you’re working from a from-scratch build, the article on building a WordPress theme from scratch covers exactly how these two files relate.

Enqueueing the Lottie Player Script Correctly

WordPress has a specific, correct way to load JavaScript: the wp_enqueue_script() function, called inside a function hooked to wp_enqueue_scripts. Loading scripts any other way – like pasting a <script> tag directly into header.php – works but skips WordPress’s dependency management and can cause scripts to load twice or in the wrong order. Here’s the pattern I use to load the Lottie Player from a CDN:

function ivorymiracle_enqueue_lottie_player() {
    wp_enqueue_script(
        'lottie-player',
        'https://unpkg.com/@lottiefiles/lottie-player@latest/dist/lottie-player.js',
        array(),
        '2.0.8',
        true
    );
}
add_action( 'wp_enqueue_scripts', 'ivorymiracle_enqueue_lottie_player' );

The true at the end loads the script in the footer, which keeps it from blocking your page’s initial render. That detail matters for Core Web Vitals. The WordPress Plugin Handbook’s guide to enqueueing scripts documents this pattern in full if you want the underlying reasoning.

Step 4: Add the Lottie Player to the Navigation Markup

With the script loading correctly, you can drop the animation directly into your navbar’s HTML.

Inserting the <lottie-player> Web Component

The Lottie Player is a custom HTML element. Use it like any other tag once its script has loaded:

<lottie-player
  src="/wp-content/uploads/2026/09/navbar-icon.json"
  background="transparent"
  speed="1"
  style="width: 48px; height: 48px;"
  loop
  autoplay
></lottie-player>

Upload your JSON file to the WordPress media library like any other asset, then reference its URL in the src attribute. Replace autoplay with trigger-based playback if you want the animation to fire on hover or click instead of on page load.

Structuring the Navbar Markup Around the Animation

Here’s a complete navbar structure with the Lottie Player embedded next to the logo and a hamburger toggle for mobile:

<header class="site-header">
  <nav class="animated-navbar" aria-label="Primary navigation">
    <a href="/" class="nav-logo">
      <lottie-player src="/wp-content/uploads/2026/09/navbar-icon.json"
        background="transparent" speed="1" style="width:40px;height:40px;" loop></lottie-player>
    </a>
    <ul class="nav-links">
      <li><a href="/about">About</a></li>
      <li><a href="/services">Services</a></li>
      <li><a href="/contact">Contact</a></li>
    </ul>
    <button class="hamburger" aria-label="Toggle menu" aria-expanded="false">
      <span></span><span></span><span></span>
    </button>
  </nav>
</header>

The aria-label on the <nav> element and the aria-expanded attribute on the button matter more than they look like they do. We’ll come back to them in Step 7.

Step 5: Style the Navbar With CSS for Smooth Transitions

Lottie handles the icon or logo animation. CSS handles everything else: hover states, the shrinking header on scroll, and the sliding mobile menu.

Writing CSS Transitions for Hover and State Changes

CSS transitions are the workhorse of navbar animation, and they’re far cheaper on the rendering engine than animating properties like width or top. Stick to animating transform and opacity:

.nav-links a {
  position: relative;
  transition: color 0.2s ease;
}

.nav-links a::after {
  content: '';
  position: absolute;
  left: 0;
  bottom: -4px;
  width: 0;
  height: 2px;
  background: currentColor;
  transition: width 0.25s ease;
}

.nav-links a:hover::after {
  width: 100%;
}

.site-header {
  transition: background-color 0.3s ease, box-shadow 0.3s ease;
}

.site-header.scrolled {
  background-color: rgba(255, 255, 255, 0.96);
  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08);
}

The easing curve changes how the motion feels. ease is a safe, natural default. ease-in-out feels more deliberate for larger movements like a full mobile menu sliding into view.

Responsive Adjustments for Mobile Hamburger Menus

Your hamburger menu needs separate transition logic from desktop hover states:

.nav-links {
  display: flex;
  gap: 24px;
}

@media (max-width: 768px) {
  .nav-links {
    position: fixed;
    top: 0;
    right: -100%;
    height: 100vh;
    width: 70%;
    flex-direction: column;
    background: #fff;
    transition: right 0.35s ease;
  }

  .nav-links.open {
    right: 0;
  }

  .hamburger {
    display: block;
  }
}

This slides the mobile menu in from off-screen rather than fading it in place, which reads as more intentional and gives users a clear sense of where the menu exists on the page.

Step 6: Wire Up Scroll and Hover Triggers With JavaScript

CSS handles the visual transition. JavaScript decides when that transition happens.

Adding a Scroll Event Listener

To shrink or recolor the header once a visitor scrolls past a certain point, listen for the scroll event and toggle a class:

const header = document.querySelector('.site-header');
let lastScrollY = window.scrollY;

window.addEventListener('scroll', () => {
  const currentScrollY = window.scrollY;
  header.classList.toggle('scrolled', currentScrollY > 40);
  lastScrollY = currentScrollY;
});

Browsers fire scroll events very frequently – sometimes dozens of times per second. On a heavier page, you’ll want to debounce or throttle this listener. The MDN Web Docs entry on the scroll event covers throttling patterns in detail if your navbar does more than a simple class toggle.

Adding a Click Event Listener for the Hamburger Menu

The hamburger button needs a click listener that toggles both the visible menu and its ARIA state:

const hamburger = document.querySelector('.hamburger');
const navLinks = document.querySelector('.nav-links');

hamburger.addEventListener('click', () => {
  const isOpen = navLinks.classList.toggle('open');
  hamburger.setAttribute('aria-expanded', isOpen);
});

If you want the Lottie-animated logo to react to the same click – for instance, switching from a static state to spinning – call the player’s methods like lottiePlayer.play() or lottiePlayer.setDirection(-1) from inside the event handler.

Watching this responsive CSS-only sidebar navbar build helps if you want to see the transition logic in motion before adjusting your own values.

Step 7: Test Performance and Accessibility

An animated navbar that looks great on desktop but locks up on a phone, or that a screen reader user can’t operate, isn’t finished. This step is non-negotiable, and every competing gallery page skips it entirely.

Testing Load Time and Animation Smoothness

Open your browser’s developer tools and check the Network and Performance tabs on both a fast connection and a throttled "Slow 3G" simulation. Watch specifically for:

  1. Total script weight added. The Lottie Player library is roughly 30KB gzipped; your JSON file should add far less than your images do.
  2. Frame rate during animation. Chrome DevTools’ Performance panel shows dropped frames if your animation or scroll listener is too demanding.
  3. Layout shift. Define dimensions for animated elements so the browser doesn’t reflow the page as the Lottie Player loads, which hurts your Cumulative Layout Shift score.

Adding ARIA Roles and Respecting Reduced-Motion Preferences

Accessibility is a design constraint from the start, not an afterthought. The W3C’s WAI-ARIA Authoring Practices Guide documents the expected roles and keyboard behavior for navigation menus. Following it means:

  • Using a real <nav> element with an aria-label, not a generic <div>.
  • Setting aria-expanded="true" or "false" on your hamburger button and updating it with JavaScript, not leaving it static.
  • Making every interactive element reachable and operable with the keyboard alone, not just mouse or touchscreen.
  • Respecting the prefers-reduced-motion media feature so visitors who experience motion sickness or vestibular discomfort don’t see your animation forced on them.

MDN Web Docs documents prefers-reduced-motion in detail:

@media (prefers-reduced-motion: reduce) {
  .site-header,
  .nav-links a::after,
  .nav-links {
    transition: none;
  }
}
const prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
if (prefersReducedMotion) {
  lottiePlayer.setSpeed(0);
}

Accessibility and performance QA checklist:

  • Navbar is fully operable using only Tab and Enter keys
  • Hamburger button toggles aria-expanded correctly
  • Screen reader announces the nav landmark and link labels correctly
  • prefers-reduced-motion disables or slows non-essential animation
  • Lottie JSON file is under roughly 50 to 100KB
  • No layout shift occurs when the animation loads
  • Animation does not autoplay in a way that distracts from page content
  • Navbar tested on at least one real mobile device, not only browser resize

If you want a broader framework for this beyond just the navbar, the article on designing an accessible website applies the same principles to a full page.

Troubleshooting Common Problems

A few issues come up often enough that they’re worth addressing directly.

The animation doesn’t load at all. Check your browser console first. Nine times out of ten, either the enqueued script didn’t fire because the function wasn’t hooked to wp_enqueue_scripts correctly, or the JSON file’s path is wrong because it points to a local file path instead of the uploaded media URL.

The animation triggers twice. This usually means the script got enqueued more than once, often because both a parent and child theme load it, or a page builder plugin loads its own copy of the Lottie library. Check your page source for duplicate <script> tags referencing the same library.

The animation plays but looks choppy. Go back to your After Effects composition and check for embedded raster layers or excessive keyframes. Choppy Lottie animation is almost always a file complexity problem, not a WordPress or browser problem.

The mobile menu flickers or jumps on open. This is typically a CSS specificity conflict, often from a theme’s default menu styles fighting your custom classes. Using more specific selectors, or scoping your styles under a unique parent class, usually resolves it.

Choosing Between CSS-Only and Lottie for Your Next Build

Not every navbar needs Lottie. Here’s how I decide which approach fits a given project:

Approach Good Fit When Skill Level Needed File Weight
CSS-only transitions Simple hover states, underline links, basic mobile menus Beginner Minimal, no extra files
Lottie-based animation Custom logo animation, icon morphing, brand-specific interactions Intermediate Small JSON file plus ~30KB player library

If your site just needs a link to underline on hover, don’t reach for Lottie. Plain CSS transitions do the job with zero added weight. Reach for Lottie when the design calls for something CSS genuinely can’t produce, like a logo that morphs shape or an icon with a multi-stage animation sequence.

Next Steps: Refining Your Animated Navbar

Once your navbar is live, tested, and accessible, there’s still room to refine it. Look at real, working examples for inspiration on what to add next – a mega menu reveal or an active-link indicator that slides between items. You can browse animated navbar examples for ideas grounded in actual production sites.

If Lottie is new to you, adding Lottie animations to WordPress goes deeper into using it elsewhere on your site beyond just the header. If you’d rather have this built for you, our custom WordPress theme development services cover exactly this kind of first-party motion design work, including motion design with Lottie for logos, navigation, and interactive page elements.

Frequently Asked Questions

What is a Lottie Player and why use it for a navbar?

The Lottie Player is a lightweight web component that renders vector animations exported from a JSON file, rather than a video or GIF. It works well for navbars because it stays sharp at any resolution, loads fast, and can be controlled with JavaScript to play, pause, or reverse in response to user actions like hover or scroll.

Do I need to know JavaScript to build an animated navbar?

Not for the basics. Hover-based transitions work with CSS alone. You’ll need beginner-level JavaScript for scroll-triggered animation, hamburger menu toggling, and controlling a Lottie Player’s playback state.

Will an animated navbar slow down my WordPress site?

It can, if the Lottie JSON file is bloated with raster images or excessive keyframes, or if scripts are enqueued incorrectly and load render-blocking. Keep your JSON file small, load scripts in the footer, and test with browser developer tools before publishing.

How do I make an animated navbar accessible?

Use a real <nav> element with an aria-label, keep every interactive element keyboard-operable, update aria-expanded on your menu toggle with JavaScript, and respect the prefers-reduced-motion media feature so animation-sensitive visitors aren’t forced to see it.

What’s the difference between a CSS-only and a Lottie-based navbar animation?

CSS-only animation handles simple state changes like hover underlines or a sliding mobile menu with no extra files needed. Lottie handles more elaborate, designer-made motion like a morphing logo or multi-stage icon animation, at the cost of loading a small JSON file and the Lottie Player script.

Can I add an animated navbar without a child theme?

You can technically edit a parent theme’s files directly, but any update to that theme will erase your changes. A child theme or a fully custom theme is the only reliable way to keep your animated navbar intact long term.

How large should a Lottie JSON file be for a navbar?

I keep navbar-specific Lottie files under roughly 50KB by simplifying the After Effects composition before export and avoiding embedded raster images. Anything over 200KB for a simple navbar icon usually signals unnecessary complexity in the source file.

What is enqueueing a script in WordPress?

Enqueueing is WordPress’s built-in system for loading CSS and JavaScript files correctly using the wp_enqueue_script() and wp_enqueue_style() functions. It manages dependencies and load order so scripts don’t conflict or load more than once, unlike pasting a <script> tag directly into a template file.

How do I test my animated navbar on mobile devices?

Use your browser’s device toolbar for a first pass, but always confirm on at least one real phone or tablet. Touch targets, tap responsiveness, and animation smoothness on real hardware often differ from what a resized desktop browser window shows you.

What should I do if my navbar animation doesn’t load?

Check the browser console for a 404 on the JSON file path or the Lottie Player script itself. Confirm your wp_enqueue_script() function is correctly hooked to wp_enqueue_scripts, and check for a duplicate script being loaded by a plugin or parent theme, which can silently cancel out your custom version.

Takeaway

Building an animated navbar isn’t about chasing a trend. It’s a contained project that teaches how your entire WordPress theme fits together: markup, enqueued scripts, CSS transitions, and JavaScript event listeners all working on one visible piece of the page. Once you’ve built one navbar this way, applying the same trigger logic elsewhere – in a hero section or a call-to-action button – becomes far less intimidating. If you’d rather have a developer handle the build end to end, that’s where WordPress web design and UI/UX services begins the conversation.

Sources

Conversation

One thought so far

Good work gets better when people bring thoughtful questions, ideas, and perspective.

Leave a considered reply

Your email stays private. Required fields are marked *.