Skip to main content

Theme config

Theme mode

Color palette

Grays

Border radii/radiuses/radiopedes/you know
Border radius
Field border radius
Button border radius
All
Components
Guides
API
Recent

    Components

    Tabs

    The Tabs are radio inputs and the Panels are just divs that show and hide based on the radio inputs' :checked state.

    Full supportSupported since v123.Full supportSupported since v120.Full supportSupported since v17.5.

    Anatomy

    Profile settings and information.
    General account settings.
    • .ui-tabs

      Container element.

    • .ui-tab-input

      A visually hidden radio input that holds a tab's state.

    • .ui-tab-label

      A tab.

    • .ui-tab-panel

      The panel of the selected tab.

    Basics

    Profile settings and information.
    General account settings.
    Manage your notifications.
    <div class="ui-tabs" role="tablist">
    <input
    type="radio"
    name="basic-tabs"
    id="tab-profile"
    class="ui-tab-input"
    checked
    aria-controls="panel-profile"
    />
    <label for="tab-profile" class="ui-tab-label" role="tab">Profile</label>
    <div
    id="panel-profile"
    class="ui-tab-panel"
    role="tabpanel"
    aria-labelledby="tab-profile"
    >
    Profile settings and information.
    </div>
    <input
    type="radio"
    name="basic-tabs"
    id="tab-settings"
    class="ui-tab-input"
    aria-controls="panel-settings"
    />
    <label for="tab-settings" class="ui-tab-label" role="tab">Settings</label>
    <div
    id="panel-settings"
    class="ui-tab-panel"
    role="tabpanel"
    aria-labelledby="tab-settings"
    >
    General account settings.
    </div>
    <input
    type="radio"
    name="basic-tabs"
    id="tab-notifications"
    class="ui-tab-input"
    aria-controls="panel-notifications"
    />
    <label for="tab-notifications" class="ui-tab-label" role="tab"
    >Notifications</label
    >
    <div
    id="panel-notifications"
    class="ui-tab-panel"
    role="tabpanel"
    aria-labelledby="tab-notifications"
    >
    Manage your notifications.
    </div>
    </div>

    Accessibility

    The tab system uses standard radio inputs and labels, so we get group management and keyboard support for free!

    Tab List

    ElementAttributeDescription
    .ui-tabsrole="tablist"Identifies the element as a container for a set of tabs.
    inputnameGroups the radio buttons together for exclusive selection.
    labelrole="tab"Identifies the element as a tab to assistive technology.

    Tab Panel

    The content area associated with a tab:

    AttributeValueDescription
    role"tabpanel"Identifies the element as a tab panel.
    aria-labelledbystringLinks the panel to its trigger ID.

    Keyboard Interaction

    • Tab: Moves focus to the active tab trigger (the radio button). Pressing Tab again moves focus out of the tab list to the next focusable element.
    • Right Arrow / Down Arrow: Moves focus to the next tab and activates it.
    • Left Arrow / Up Arrow: Moves focus to the previous tab and activates it.

    API

    Tabs API

    TypeModifiersDefaultDescription
    Group.ui-tab-input[name]-The name shared by the tab inputs. Generated when omitted.

    Parts

    PartDescription
    .ui-tabsContainer element.
    .ui-tab-inputA visually hidden radio input that holds a tab's state.
    .ui-tab-labelA tab.
    .ui-tab-panelThe panel of the selected tab.

    The root needs role="tablist". Each tab is an input.ui-tab-input[type="radio"], followed by its label.ui-tab-label[role="tab"] and .ui-tab-panel[role="tabpanel"].

    Tabs item API

    TypeModifiersDefaultDescription
    State[checked]-Selects the tab initially.

    Parts

    PartDescription
    input.ui-tab-inputThe radio input for a tab, followed by the tab and the panel.

    Tabs tab API

    Parts

    PartDescription
    label.ui-tab-labelThe tab.

    Tabs panel API

    Parts

    PartDescription
    .ui-tab-panelThe panel.

    Browser support

    Full supportSupported since v123.Full supportSupported since v120.Full supportSupported since v17.5.

    See also the full browser support guide.

    Installation

    @layer components.root {
    :where(.ui-tabs) {
    --_accent-color: var(--primary);
    --_bg-color: transparent;
    align-items: flex-start;
    display: flex;
    flex-wrap: wrap;
    gap: 0 var(--size-1);
    position: relative;
    & > .ui-tab-input[type="radio"] {
    /* utils > .ui-sr-only */
    /* TODO: use mixin for this when available */
    block-size: 1px;
    clip-path: inset(50%);
    inline-size: 1px;
    overflow: hidden;
    position: absolute;
    white-space: nowrap;
    &:checked {
    /* Checked Tab */
    & + [role="tab"],
    & + .ui-tab-label {
    border-block-end-color: var(--_accent-color);
    color: var(--_accent-color);
    /* Checked Panel */
    & + [role="tabpanel"],
    & + .ui-tab-panel {
    display: block;
    }
    }
    }
    &:focus-visible {
    & + [role="tab"],
    & + .ui-tab-label {
    --focus-ring-color: var(--text-muted);
    --focus-ring-offset: calc(-1 * var(--size-2));
    outline: var(--focus-ring-width) var(--focus-ring-style)
    var(--focus-ring-color);
    outline-offset: var(--focus-ring-offset);
    }
    }
    }
    /* Tab */
    & > [role="tab"],
    & > .ui-tab-label {
    align-items: center;
    background-color: transparent;
    border-bottom: 2px solid transparent;
    border-radius: 0;
    color: var(--text-muted);
    cursor: pointer;
    display: inline-flex;
    font-weight: 600;
    justify-content: center;
    line-height: var(--font-lineheight-4);
    order: 1;
    padding: var(--size-2) var(--size-3);
    position: relative;
    transition: color 0.1s;
    user-select: none;
    &:hover {
    background-color: light-dark(
    oklch(from var(--_accent-color) calc(l * 0.75) none h / 5%),
    oklch(from var(--_accent-color) calc(l * 1.25) none h / 5%)
    );
    }
    }
    /* Tab Panel */
    & > [role="tabpanel"],
    & > .ui-tab-panel {
    display: none;
    inline-size: 100%;
    order: 2;
    }
    }
    }