Tabs - National Design System

Group related content into a single surface where users switch between views without leaving the page

Standard Tabs

The default text-only tab strip. Reach for this when labels alone are enough to distinguish the panels and you want the broadest layout flexibility across vertical, divider, and card views.

With Leading Icons

Icons before each label help users scan and identify tabs quickly

Built-in Features

Auto-initialization

Activates when .nds-tabs is on the page. Tab switching, keyboard handling, and scroll behavior attach automatically.

Full Keyboard Navigation

Arrow keys move between tabs, Home and End jump to first and last, and Enter or Space activates the focused tab.

RTL-Aware Navigation

Arrow key direction reverses automatically in RTL layouts so navigation always feels natural to the reading direction.

Overflow Scrolling

Long tab lists scroll horizontally with gradient fade indicators, drag-to-scroll, mouse wheel support, and a show-more button.

Vertical Layout

Add nds-vertical for a side-stacked tab list with sticky positioning and vertical indicator bars.

High Contrast and Reduced Motion

Enhanced borders appear in high-contrast mode, and all transitions are disabled when the user prefers reduced motion.

Tab Change Events

Every tab switch dispatches an nds:tab:change event with the new and previous tab and panel references.

Programmatic Control

Switch tabs, query the active panel, or destroy instances through the JS API on NDS.Tabs or each element's .ndsTabs property.

Usage Guidelines

Best Practices

  • Use tabs to organize related content that users access one section at a time, such as settings categories, service details, or dashboard views
  • Use tabs for content that benefits from quick comparison, where switching between panels helps users evaluate options without leaving the page
  • Use vertical tabs when the tab list is long or when labels need more space, such as multi-step configuration panels or category navigation
  • Do not use tabs for sequential workflows where the user must complete steps in order. Use a Stepper instead
  • Do not use tabs for simple content that fits on one page without segmentation. Unnecessary tabs add interaction cost
  • Choose card view when tabs appear inside a content area that already has a background, to visually contain the tab group
  • Add the divider modifier when you need a clear visual boundary between the tab list and the panel content
  • Keep tab labels short (one to three words). Long labels cause excessive scrolling in horizontal layouts
  • Add icons to tabs when they represent distinct categories that benefit from visual differentiation, but avoid icons on text-heavy labels where they add clutter
  • Aim for three to seven visible tabs. Beyond that, the overflow scroll mechanism handles the rest, but users may not discover hidden tabs easily
  • Structure tab panel content using nds-block with nds-block-title headings. Multiple content blocks per panel create clear visual sections within a single tab
  • Place the most frequently accessed tab first, as it becomes the default active panel on page load

Modifier Classes

Class Description
nds-vertical Switches to a side-stacked vertical tab layout with sticky positioning
nds-divided Adds a divider line between the tab list and panel content
nds-center Centers the tab list horizontally within the container
nds-lg Increases tab button height for a larger touch target
nds-card nds-stroke nds-shadow Wraps the tab group in a card container with border and shadow

CSS Custom Properties

Property Default Description
--scroll-fade 48px Width of the gradient fade at the edges of an overflowing tab list (set on the inner .nds-scroll-more)
--btn-indicator-size 3px Thickness of the active tab indicator bar and divider line

JavaScript API

The NDS.Tabs API provides methods to create, switch, and query tab instances. Each initialized .nds-tabs element stores its instance on the .ndsTabs DOM property.

// ── Global API ────────────────────────────────────── NDS.Tabs.init(); // Re-scan page and initialize new .nds-tabs elements NDS.Tabs.reinit(); // Alias for init(), useful after dynamic content changes NDS.Tabs.create(container); // Create and return a new NDSTabs instance for a DOM element // ── Instance API ──────────────────────────────────── // Access via element.ndsTabs const tabs = document.querySelector('#myTabs').ndsTabs; tabs.switchTo(2); // Switch to the third tab (zero-based index) tabs.getActiveTabIndex(); // Returns the current active tab index tabs.getActiveTab(); // Returns the active tab button element tabs.getActivePanel(); // Returns the active panel element tabs.destroy(); // Remove all event listeners and clean up // ── Custom Event ──────────────────────────────────── // Dispatched on the .nds-tabs container element, bubbles up document.addEventListener('nds:tab:change', (e) => { e.detail.tabIndex; // New active tab index (number) e.detail.tab; // New active tab button element e.detail.panel; // New active panel element e.detail.previousTab; // Previously active tab button element e.detail.previousPanel; // Previously active panel element });
Was this page useful?
60% of users said Yes from 2843 Feedbacks