Skip to content

Vertical Tabs

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

Accordions & TabsHTMLCSSJavaScriptany framework

Copy into your project

HTML
<div class="nuda-vtabs">
  <div class="nuda-vtabs__sidebar" role="tablist" aria-orientation="vertical">
    <button class="nuda-vtabs__tab is-active" role="tab" data-tab="a">Tab A</button>
    <button class="nuda-vtabs__tab" role="tab" data-tab="b">Tab B</button>
    <button class="nuda-vtabs__tab" role="tab" data-tab="c">Tab C</button>
  </div>
  <div class="nuda-vtabs__panel is-active" data-panel="a" role="tabpanel">Panel A content</div>
  <div class="nuda-vtabs__panel" data-panel="b" role="tabpanel">Panel B content</div>
  <div class="nuda-vtabs__panel" data-panel="c" role="tabpanel">Panel C content</div>
</div>
CSS
/* Vertical Tabs
   Side-by-side tabs with left sidebar.
   Customize: --vtab-accent */

.nuda-vtabs {
  --vtab-accent: #e4ff54;
  display: flex;
  gap: 0.5rem;
  max-width: 600px;
}

.nuda-vtabs__sidebar {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 120px;
}

.nuda-vtabs__tab {
  padding: 0.6rem 0.75rem;
  font-size: 0.85rem;
  color: #888;
  background: none;
  border: none;
  border-left: 2px solid transparent;
  border-radius: 0 8px 8px 0;
  cursor: pointer;
  text-align: left;
  transition: all 0.2s ease;
}

.nuda-vtabs__tab:hover { color: #ccc; background: rgba(255, 255, 255, 0.02); }

.nuda-vtabs__tab.is-active {
  color: var(--vtab-accent);
  background: rgba(228, 255, 84, 0.06);
  border-left-color: var(--vtab-accent);
}

.nuda-vtabs__panel {
  display: none;
  flex: 1;
  padding: 1rem;
  background: rgba(255, 255, 255, 0.02);
  border: 1px solid rgba(255, 255, 255, 0.05);
  border-radius: 10px;
  color: #ccc;
  font-size: 0.85rem;
  animation: nuda-vtab-fade 0.3s ease-out;
}

.nuda-vtabs__panel.is-active { display: block; }

@keyframes nuda-vtab-fade {
  from { opacity: 0; transform: translateX(8px); }
  to { opacity: 1; transform: translateX(0); }
}

@media (prefers-reduced-motion: reduce) {
  .nuda-vtabs__tab { transition: none; }
  .nuda-vtabs__panel { animation: none; }
}
JavaScript
/* Vertical Tabs — Switch panels */

(function () {
  var containers = document.querySelectorAll('.nuda-vtabs');
  containers.forEach(function (vtabs) {
    var tabs = vtabs.querySelectorAll('.nuda-vtabs__tab');
    var panels = vtabs.querySelectorAll('.nuda-vtabs__panel');

    tabs.forEach(function (tab) {
      tab.addEventListener('click', function () {
        tabs.forEach(function (t) { t.classList.remove('is-active'); });
        panels.forEach(function (p) { p.classList.remove('is-active'); });
        tab.classList.add('is-active');
        var panel = vtabs.querySelector('[data-panel="' + tab.dataset.tab + '"]');
        if (panel) panel.classList.add('is-active');
      });
    });
  });
})();

How to use Vertical Tabs

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 accordions & tabs components

← Browse all NudaUI components