Skip to content

Tab Slide

A copy-paste navigation component in pure HTML, CSS & vanilla JS. Zero dependencies, framework-agnostic, MIT-licensed.

NavigationHTMLCSSJavaScriptany framework

Copy into your project

HTML
<div class="nuda-tab-slide" role="tablist" aria-label="Content tabs">
  <button class="nuda-tab-slide__tab active" role="tab" aria-selected="true">Overview</button>
  <button class="nuda-tab-slide__tab" role="tab" aria-selected="false">Features</button>
  <button class="nuda-tab-slide__tab" role="tab" aria-selected="false">Pricing</button>
  <div class="nuda-tab-slide__indicator"></div>
</div>
CSS
/* Tab Slide
   Tabs with animated sliding indicator bar.
   Customize: --tab-accent, --tab-text, --tab-border */

.nuda-tab-slide {
  --tab-accent: #e4ff54;
  --tab-text: #999;
  --tab-border: rgba(255, 255, 255, 0.1);
  display: flex;
  position: relative;
  border-bottom: 1px solid var(--tab-border);
}

.nuda-tab-slide__tab {
  background: none;
  border: none;
  color: var(--tab-text);
  font-size: 0.85rem;
  padding: 0.75rem 1.25rem;
  cursor: pointer;
  transition: color 0.3s ease;
}

.nuda-tab-slide__tab:hover {
  color: #fff;
}

.nuda-tab-slide__tab.active {
  color: var(--tab-accent);
}

.nuda-tab-slide__indicator {
  position: absolute;
  bottom: -1px;
  left: 0;
  height: 2px;
  background: var(--tab-accent);
  border-radius: 2px;
  transition: transform 0.3s ease, width 0.3s ease;
}

@media (prefers-reduced-motion: reduce) {
  .nuda-tab-slide__indicator {
    transition: none;
  }
  .nuda-tab-slide__tab {
    transition: none;
  }
}
JavaScript
/* Tab Slide — Indicator positioning
   Moves the indicator to align with the active tab. */

(function () {
  const tablist = document.querySelector('.nuda-tab-slide');
  if (!tablist) return;

  const tabs = tablist.querySelectorAll('.nuda-tab-slide__tab');
  const indicator = tablist.querySelector('.nuda-tab-slide__indicator');
  if (!indicator) return;

  function moveIndicator(tab) {
    indicator.style.width = tab.offsetWidth + 'px';
    indicator.style.transform = 'translateX(' + tab.offsetLeft + 'px)';
  }

  tabs.forEach(function (tab) {
    tab.addEventListener('click', function () {
      tabs.forEach(function (t) {
        t.classList.remove('active');
        t.setAttribute('aria-selected', 'false');
      });
      tab.classList.add('active');
      tab.setAttribute('aria-selected', 'true');
      moveIndicator(tab);
    });
  });

  // Initialize indicator position
  var active = tablist.querySelector('.nuda-tab-slide__tab.active');
  if (active) moveIndicator(active);
})();

How to use Tab Slide

Paste the HTML where you need it and the CSS into a global stylesheet (or a <style> tag). Every class is prefixed nuda- so it never collides with Tailwind or your own styles. Tweak the CSS custom properties to match your design system.

Works in React, Vue, Svelte, Astro, Next.js, Nuxt, Laravel Blade, Django, Rails — or a single .html file. No npm install, no build step.

More navigation components

← Browse all NudaUI components