Tabs
Tabs organize groups of related content that are at the same level of hierarchy.
<md-gb-tabs aria-label="Travel">
<md-gb-tab selected><span slot="label">Flights</span></md-gb-tab>
<md-gb-tab><span slot="label">Trips</span></md-gb-tab>
<md-gb-tab><span slot="label">Explore</span></md-gb-tab>
</md-gb-tabs>Install with shadcn/ui: npx shadcn@latest add https://material-web.dev/3.0/r/md-tabs.json (setup)
Usage guidelines
Link to “Usage guidelines”- Same level of hierarchy. Tabs switch between views of related content that are peers. Don't use them for steps in a flow.
- Primary or secondary. Primary tabs sit at the top of the content under a top app bar and show the main destinations. Secondary tabs split a content area further. Use one type in a bar.
- Short labels. Keep labels to a word or two. Use icons only when they are simple and recognizable.
- Avoid dense tabs by default. Lowering the density shrinks the targets below 48px, so let people opt in.
Anatomy
Link to “Anatomy”A tab list holds tabs, and each tab has an optional icon, a label and an optional badge. Tab panels hold the content.
<md-gb-tabs id="anatomy-tabs" aria-label="Mail">
<md-gb-tab selected>
<md-gb-icon>inbox</md-gb-icon>
<span slot="label">Inbox</span>
<span class="badge badge-large tab-badge" slot="badge">3</span>
</md-gb-tab>
<md-gb-tab>
<md-gb-icon>send</md-gb-icon>
<span slot="label">Sent</span>
</md-gb-tab>
</md-gb-tabs>
<md-gb-tab-panels for="anatomy-tabs">
<div role="tabpanel">Three new messages.</div>
<div role="tabpanel">Messages you sent.</div>
</md-gb-tab-panels>Examples
Link to “Examples”Primary and secondary
Link to “Primary and secondary”Tabs are primary by default. Set variant="secondary" for secondary tabs, which put the icon beside the label.
<md-gb-tabs variant="secondary" aria-label="Trip type">
<md-gb-tab selected>
<md-gb-icon>flight</md-gb-icon>
<span slot="label">Travel</span>
</md-gb-tab>
<md-gb-tab>
<md-gb-icon>hotel</md-gb-icon>
<span slot="label">Hotel</span>
</md-gb-tab>
</md-gb-tabs>Icons
Link to “Icons”Put an icon before the label, or leave out the label for icon-only tabs. Icon-only tabs need an aria-label.
<md-gb-tabs aria-label="Travel">
<md-gb-tab selected>
<md-gb-icon>flight</md-gb-icon>
<span slot="label">Flights</span>
</md-gb-tab>
<md-gb-tab>
<md-gb-icon>luggage</md-gb-icon>
<span slot="label">Trips</span>
</md-gb-tab>
</md-gb-tabs>
<md-gb-tabs aria-label="Media">
<md-gb-tab selected aria-label="Photos"><md-gb-icon>photo</md-gb-icon></md-gb-tab>
<md-gb-tab aria-label="Videos"><md-gb-icon>videocam</md-gb-icon></md-gb-tab>
</md-gb-tabs>Badges
Link to “Badges”A tab can show a badge in the badge slot for counts or status.
<md-gb-tabs aria-label="Mail">
<md-gb-tab selected>
<span slot="label">Inbox</span>
<span class="badge badge-large tab-badge" slot="badge">3</span>
</md-gb-tab>
<md-gb-tab><span slot="label">Sent</span></md-gb-tab>
</md-gb-tabs>Tab panels
Link to “Tab panels”Link each tab to its panel with tabpanel, the id of a panel such as md-aria-tabpanel. Only the selected panel is shown.
<md-gb-tabs aria-label="Travel">
<md-gb-tab selected tabpanel="flights-panel"><span slot="label">Flights</span></md-gb-tab>
<md-gb-tab tabpanel="trips-panel"><span slot="label">Trips</span></md-gb-tab>
</md-gb-tabs>
<md-aria-tabpanel id="flights-panel">Search one-way and round-trip fares.</md-aria-tabpanel>
<md-aria-tabpanel id="trips-panel">Your upcoming and past bookings.</md-aria-tabpanel>Swipeable panels
Link to “Swipeable panels”md-gb-tab-panels holds the panels next to the tabs and lets people swipe between them. It pairs with the previous tab list, or with for, the id of one. Set gestures-disabled to turn swiping off.
<md-gb-tabs id="places" aria-label="Places">
<md-gb-tab selected><span slot="label">Flights</span></md-gb-tab>
<md-gb-tab><span slot="label">Trips</span></md-gb-tab>
<md-gb-tab><span slot="label">Explore</span></md-gb-tab>
</md-gb-tabs>
<md-gb-tab-panels for="places">
<div role="tabpanel">Search one-way and round-trip fares.</div>
<div role="tabpanel">Your upcoming and past bookings.</div>
<div role="tabpanel">Ideas for your next destination.</div>
</md-gb-tab-panels>Scrollable
Link to “Scrollable”Fixed tabs share the width equally. Set scrollable to size each tab to its label and scroll the bar when they overflow.
<md-gb-tabs scrollable aria-label="Travel">
<md-gb-tab selected><span slot="label">Flights</span></md-gb-tab>
<md-gb-tab><span slot="label">Trips</span></md-gb-tab>
<md-gb-tab><span slot="label">Hotels</span></md-gb-tab>
<md-gb-tab><span slot="label">Car rental</span></md-gb-tab>
<md-gb-tab><span slot="label">Things to do</span></md-gb-tab>
</md-gb-tabs>Density
Link to “Density”Set density from 0 (default) to -3 to remove 4px of height per step.
<md-gb-tabs density="-2" aria-label="Travel">
<md-gb-tab selected><span slot="label">Flights</span></md-gb-tab>
<md-gb-tab><span slot="label">Trips</span></md-gb-tab>
</md-gb-tabs>Selection events
Link to “Selection events”The tab list fires change when a person picks a tab. Read the new tab from selectedTabIndex.
<md-gb-tabs aria-label="Travel">
<md-gb-tab selected><span slot="label">Flights</span></md-gb-tab>
<md-gb-tab><span slot="label">Trips</span></md-gb-tab>
<md-gb-tab><span slot="label">Explore</span></md-gb-tab>
</md-gb-tabs>
<output>Selected tab: 0</output>const tabs = document.querySelector('md-gb-tabs');
const output = document.querySelector('output');
tabs.addEventListener('change', () => {
output.textContent = `Selected tab: ${tabs.selectedTabIndex}`;
});Accessibility
Link to “Accessibility”- Tabs use the
tablist,tabandtabpanelroles. Label the tab list witharia-labeloraria-labelledby, and give icon-only tabs anaria-label. - The list is one tab stop. The arrow keys move between tabs, and Space or Enter selects the focused one.
- Each tab controls a panel, and each panel is labelled by its tab. Linking them with
tabpanelormd-gb-tab-panelsdoes this for you.
Compatibility
Link to “Compatibility”Material Design 3Spec checked73% tokens
87 of 206 buildable spec units are tested, 12 are excluded with a written reason and 0 are uncovered (the target is 0). 41 of 56 token declarations match the spec (73%), and 15 have no spec token.
tabs on m3.material.io (opens in a new tab) How compliance is measured
BaselineWidely availableChrome 124Edge 124Firefox 125Safari 17.4
The component’s own CSS and JavaScript rely only on web platform features that are Baseline widely available: it works in Chrome 124, Edge 124, Firefox 125, Safari 17.4 and later.
Newer features it uses where the browser has them (progressive enhancements):
- :state() (opens in a new tab) Newly available degrades safely where it is missing
- Anchor positioning (opens in a new tab) Limited availability used inside an
@supportsguard - Cursor styles (opens in a new tab) Limited availability degrades safely where it is missing
- Flexbox (opens in a new tab) Widely available used inside an
@supportsguard - overscroll-behavior (opens in a new tab) Limited availability degrades safely where it is missing
- scrollbar-width (opens in a new tab) Newly available degrades safely where it is missing
- user-select (opens in a new tab) Limited availability used inside an
@supportsguard
Browser support Learn more about Baseline (opens in a new tab)
WAI-ARIAaxe and ARIA 1.3 passButtonTabs
Roles the component renders: button (opens in a new tab), tab (opens in a new tab), tablist (opens in a new tab), tabpanel (opens in a new tab).
Follows the WAI-ARIA Authoring Practices: Button (opens in a new tab), Tabs (opens in a new tab).
5 rendered states run through axe-core and the WAI-ARIA 1.3 role and attribute rules in a real browser, with no known gaps.
WAI-ARIA 1.3 (opens in a new tab) ARIA Authoring Practices (opens in a new tab) Accessibility
Lighthouse99 · 100 · 100 · 100
Performance Accessibility Best practices SEO
Audits under 90:
- Eliminate render-blocking resources
- Minify JavaScript
- Enable text compression
- Network dependency tree
- Render blocking requests
Lighthouse 12.8.2 (desktop, 2026-11-08) on the component alone: its first example on a page of its own, without this site's shell. The modules are the development build (not bundled or minified), so the performance score is indicative.
API reference
Link to “API reference”<md-gb-tab>
Link to “<md-gb-tab>”A Material Design tab component.
Properties
Link to “Properties”| Property | Attribute | Type | Default |
|---|---|---|---|
selectedWhether the tab is selected. |
selected |
boolean |
|
tabpanelID of the associated md-aria-tabpanel element. |
tabpanel |
string |
Slots
Link to “Slots”| Slot | Description |
|---|---|
| default | Used to display an optional leading icon, such as <md-gb-icon>. Icons are unclassed; the tab sets --md-icon-* for them. |
badge |
Used to display an optional badge, such as <span class="badge tab-badge">. |
label |
Used to display the tab's label. <span class="tab-label"> in the default slot is equivalent. Bare text is not supported. |
CSS custom properties
Link to “CSS custom properties”| Property | Description |
|---|---|
--badge-space |
|
--focus-indicator-clearance |
|
--focus-indicator-inset |
|
--focus-indicator-shape |
|
--icon-badge-inset |
|
--icon-color |
|
--icon-label-space |
|
--icon-size |
|
--label-text |
|
--label-text-axes |
|
--label-text-color |
|
--label-text-tracking |
|
--leading-space |
|
--stacked-icon-label-space |
|
--tab-scroll-margin |
|
--trailing-space |
<md-gb-tab-panels>
Link to “<md-gb-tab-panels>”The swipeable content panels of a set of Material Design tabs.
Properties
Link to “Properties”| Property | Attribute | Type | Default |
|---|---|---|---|
gesturesDisabledWhether to turn off swiping between panels. |
gestures-disabled |
boolean |
false |
htmlForThe id of the <md-gb-tabs> these panels belong to. |
for |
string |
'' |
Slots
Link to “Slots”| Slot | Description |
|---|---|
| default | The tab panels: elements with role="tabpanel", such as <md-aria-tabpanel> or <div role="tabpanel">. |
CSS custom properties
Link to “CSS custom properties”| Property | Description |
|---|---|
--transition-duration |
Duration of a slide between panels. |
--transition-easing |
Easing of a slide between panels. |
<md-gb-tabs>
Link to “<md-gb-tabs>”A Material Design tabs component.
Properties
Link to “Properties”| Property | Attribute | Type | Default |
|---|---|---|---|
alignWhere fixed tabs sit when the window is wider than compact: center (default) or start, the leading edge. tabs.md, Responsive layout: "The group of tabs should use a fluid margin and align to the center or leading edge of the body region." At compact windows the tabs fill the full width. |
align |
"start" |
"center" |
autoSelectWhether or not to automatically select a tab when it is focused. |
autoselect |
boolean |
false |
densityThe density, from 0 (default) to -3. Each step down removes 4px from the tabs' height (48px, or 64px with icon and label); values are clamped to that range. tabs.md "Avoid applying density by default": dense tabs are below the 48x48 CSS pixel target, so let people opt in (a denser layout or theme) and keep the controls that change it at 48x48. |
density |
Density |
|
orientationOrientation of the tablist ('horizontal' or 'vertical'). |
orientation |
"horizontal" |
"vertical" |
scrollableScrollable tabs: each tab's width is defined by its label (tabs.md) rather than every tab taking the width of the widest, and the bar scrolls when they overflow. Fixed tabs (the default) are equal. |
scrollable |
boolean |
false |
scrollBehaviorHow the tabs react to scrolling: hide scrolls them off the screen when the page scrolls down and returns them when it scrolls up (tabs.md). Tabs attached to an app bar (its tabs slot) leave this unset: the app bar moves them with itself as one unit. |
scroll-behavior |
"hide" |
|
scrollTargetThe id of the element whose scrolling drives scroll-behavior. Defaults to the window. |
scroll-target |
string |
'' |
selectedTabIndexThe index of the currently selected tab. |
selectedtabindex |
number |
|
variantThe visual variant of the tabs. |
variant |
TabsVariant |
'primary' |
Slots
Link to “Slots”| Slot | Description |
|---|---|
| default | Used to display <md-gb-tab> children. |
CSS custom properties
Link to “CSS custom properties”| Property | Description |
|---|---|
--active-indicator-color |
|
--active-indicator-height |
|
--active-indicator-inset |
|
--active-indicator-min-length |
|
--active-indicator-shape |
|
--container-color |
|
--container-height |
|
--container-shape |
|
--density-step |
Tab height removed per density step. |
--divider-color |
|
--divider-thickness |