跳转到主内容

选项卡组件

最后更新:

仅 CSS 的 Tailwind CSS 选项卡,具有边框、提升、盒装和药丸样式变体。活动状态和大小,无需 JavaScript。 WCAG AA 可访问,可与 Django、HTMX、Laravel、React 和任何堆栈配合使用。

选项卡组件将内容组织成单独的部分,用户可以在不离开页面的情况下在这些部分之间进行切换。选项卡采用语义 HTML 和无线电输入模式构建,为相关信息分组提供直观的导航。 Frutjam 选项卡系统支持多种尺寸、样式和布局方向(仅 CSS 或 JavaScript 控制),使其成为仪表板、文档和选项卡式界面的理想选择。

仅 CSS,无需 JavaScript。 WCAG AA 可访问且与框架无关 - 可与 Django、HTMX、Laravel、React 和任何堆栈配合使用。

班级 类型 描述
tabs根据一组选项卡输入和内容面板的容器
tab修饰符单独选项卡无线电输入
tab-content修饰符与选项卡关联的内容面板
tab-active修饰符强制选项卡处于活动/选定状态(对于 JS 控制的选项卡)
tab-disabled修饰符选项卡的禁用外观
tabs-underline风格下划线指示器样式
tabs-lifted风格卡片式拉环样式
tabs-box风格盒装药丸式标签
tabs-vertical修饰符垂直选项卡布局,选项卡位于左侧列中
tabs-end修饰符将选项卡行与末尾对齐(LTR 中的右侧)
tabs-bottom修饰符将选项卡放置在内容面板下方
tabs-xs尺寸超小标签填充
tabs-sm尺寸小标签填充
tabs-md尺寸中等制表符填充(默认)
tabs-lg尺寸大标签填充
tabs-xl尺寸超大标签填充

基本用法

默认选项卡使用简单的活动下划线样式和单选输入。每个 tab 输入都与紧随其后的 tab-content 面板配对。

Overview content: a high-level summary of features, metrics, or status. This panel is visible by default.

Details content: in-depth information such as configuration options, data breakdown, or extended documentation.

Activity content: a timeline, event log, or recent changes relevant to this section.

html
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
<div class="tabs">
  <input type="radio" name="tabs-basic" class="tab" aria-label="Overview" checked>
  <div class="tab-content pt-4">
    <p>Overview content: a high-level summary of features, metrics, or status. This panel is visible by default.</p>
  </div>

  <input type="radio" name="tabs-basic" class="tab" aria-label="Details">
  <div class="tab-content pt-4">
    <p>Details content: in-depth information such as configuration options, data breakdown, or extended documentation.</p>
  </div>

  <input type="radio" name="tabs-basic" class="tab" aria-label="Activity">
  <div class="tab-content pt-4">
    <p>Activity content: a timeline, event log, or recent changes relevant to this section.</p>
  </div>
</div>

选项卡样式

使用 tabs-underlinetabs-boxtabs-lifted 更改选项卡条的视觉样式。

Underline style — a colored bottom border marks the active tab against a full-width separator line.
Details panel.
Activity panel.
Box style — the active tab gets a raised background inside a tinted pill container.
Details panel.
Activity panel.
Lifted style — the active tab appears as a card tab with borders that merge into the content panel below.
Details panel.
Activity panel.
html
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<div class="tabs tabs-underline">
  <input type="radio" name="style-underline" class="tab" aria-label="Overview" checked>
  <div class="tab-content pt-4">Underline style — a colored bottom border marks the active tab against a full-width separator line.</div>
  <input type="radio" name="style-underline" class="tab" aria-label="Details">
  <div class="tab-content pt-4">Details panel.</div>
  <input type="radio" name="style-underline" class="tab" aria-label="Activity">
  <div class="tab-content pt-4">Activity panel.</div>
</div>

<div class="tabs tabs-box">
  <input type="radio" name="style-box" class="tab" aria-label="Overview" checked>
  <div class="tab-content pt-4">Box style — the active tab gets a raised background inside a tinted pill container.</div>
  <input type="radio" name="style-box" class="tab" aria-label="Details">
  <div class="tab-content pt-4">Details panel.</div>
  <input type="radio" name="style-box" class="tab" aria-label="Activity">
  <div class="tab-content pt-4">Activity panel.</div>
</div>

<div class="tabs tabs-lifted">
  <input type="radio" name="style-lifted" class="tab" aria-label="Overview" checked>
  <div class="tab-content p-4">Lifted style — the active tab appears as a card tab with borders that merge into the content panel below.</div>
  <input type="radio" name="style-lifted" class="tab" aria-label="Details">
  <div class="tab-content p-4">Details panel.</div>
  <input type="radio" name="style-lifted" class="tab" aria-label="Activity">
  <div class="tab-content p-4">Activity panel.</div>
</div>

标签尺寸

将选项卡内边距从 tabs-xs 缩放到 tabs-xl 以匹配布局的密度。

Extra small tabs
Content
Small tabs
Content
Medium tabs (default)
Content
Large tabs
Content
Extra large tabs
Content
html
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<div class="tabs tabs-underline tabs-xs">
  <input type="radio" name="size-xs" class="tab" aria-label="Extra Small" checked>
  <div class="tab-content pt-3">Extra small tabs</div>
  <input type="radio" name="size-xs" class="tab" aria-label="Tab 2">
  <div class="tab-content pt-3">Content</div>
</div>

<div class="tabs tabs-underline tabs-sm">
  <input type="radio" name="size-sm" class="tab" aria-label="Small" checked>
  <div class="tab-content pt-3">Small tabs</div>
  <input type="radio" name="size-sm" class="tab" aria-label="Tab 2">
  <div class="tab-content pt-3">Content</div>
</div>

<div class="tabs tabs-underline tabs-md">
  <input type="radio" name="size-md" class="tab" aria-label="Medium" checked>
  <div class="tab-content pt-3">Medium tabs (default)</div>
  <input type="radio" name="size-md" class="tab" aria-label="Tab 2">
  <div class="tab-content pt-3">Content</div>
</div>

<div class="tabs tabs-underline tabs-lg">
  <input type="radio" name="size-lg" class="tab" aria-label="Large" checked>
  <div class="tab-content pt-3">Large tabs</div>
  <input type="radio" name="size-lg" class="tab" aria-label="Tab 2">
  <div class="tab-content pt-3">Content</div>
</div>

<div class="tabs tabs-underline tabs-xl">
  <input type="radio" name="size-xl" class="tab" aria-label="Extra Large" checked>
  <div class="tab-content pt-3">Extra large tabs</div>
  <input type="radio" name="size-xl" class="tab" aria-label="Tab 2">
  <div class="tab-content pt-3">Content</div>
</div>

带按钮的选项卡

tabbtn 结合起来,将选项卡呈现为样式按钮。 btn 类接管颜色和边框半径,同时保留选项卡选择逻辑。

Home — your primary landing panel with quick access to key actions and a summary view.

Profile — manage personal information, preferences, and account details.

Settings — configure notifications, privacy options, and connected integrations.

html
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
<div class="tabs gap-2">
  <input type="radio" name="btn-tabs" class="tab btn btn-sm" aria-label="Home" checked>
  <div class="tab-content pt-4">
    <p>Home — your primary landing panel with quick access to key actions and a summary view.</p>
  </div>

  <input type="radio" name="btn-tabs" class="tab btn btn-sm" aria-label="Profile">
  <div class="tab-content pt-4">
    <p>Profile — manage personal information, preferences, and account details.</p>
  </div>

  <input type="radio" name="btn-tabs" class="tab btn btn-sm" aria-label="Settings">
  <div class="tab-content pt-4">
    <p>Settings — configure notifications, privacy options, and connected integrations.</p>
  </div>
</div>

禁用的选项卡

添加 tab-disableddisabled 属性以防止与选项卡交互。

This tab is active and accessible.
This content is not reachable.
Another available tab panel.
html
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
<div class="tabs tabs-underline">
  <input type="radio" name="disabled-tabs" class="tab" aria-label="Available" checked>
  <div class="tab-content pt-4">This tab is active and accessible.</div>

  <input type="radio" name="disabled-tabs" class="tab tab-disabled" aria-label="Unavailable" disabled>
  <div class="tab-content pt-4">This content is not reachable.</div>

  <input type="radio" name="disabled-tabs" class="tab" aria-label="Another">
  <div class="tab-content pt-4">Another available tab panel.</div>
</div>

垂直标签

tabs-vertical 切换到网格布局,选项卡位于左侧列,内容填充右侧。列之间会自动添加全高分隔线。

General Settings

Manage your display name, language preference, and time zone.

Security

Update your password, enable two-factor authentication, and review active sessions.

Notifications

Choose which events trigger email, push, or in-app notifications.

Billing

View invoices, update your payment method, and manage your subscription plan.

html
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<div class="tabs tabs-vertical">
  <input type="radio" name="vertical" class="tab" aria-label="General" checked>
  <div class="tab-content px-6 py-2">
    <h3 class="font-semibold mb-1">General Settings</h3>
    <p>Manage your display name, language preference, and time zone.</p>
  </div>

  <input type="radio" name="vertical" class="tab" aria-label="Security">
  <div class="tab-content px-6 py-2">
    <h3 class="font-semibold mb-1">Security</h3>
    <p>Update your password, enable two-factor authentication, and review active sessions.</p>
  </div>

  <input type="radio" name="vertical" class="tab" aria-label="Notifications">
  <div class="tab-content px-6 py-2">
    <h3 class="font-semibold mb-1">Notifications</h3>
    <p>Choose which events trigger email, push, or in-app notifications.</p>
  </div>

  <input type="radio" name="vertical" class="tab" aria-label="Billing">
  <div class="tab-content px-6 py-2">
    <h3 class="font-semibold mb-1">Billing</h3>
    <p>View invoices, update your payment method, and manage your subscription plan.</p>
  </div>
</div>

底部的选项卡

tabs-bottom 翻转布局,使内容显示在选项卡条上方,这对于移动式导航栏或底部工具栏很有用。

Feed — latest posts and updates from people you follow.

Explore — discover trending topics, creators, and recommended content.

Saved — articles and posts you bookmarked for later.

html
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
<div class="tabs tabs-bottom tabs-underline">
  <input type="radio" name="bottom-tabs" class="tab" aria-label="Feed" checked>
  <div class="tab-content pb-4">
    <p>Feed — latest posts and updates from people you follow.</p>
  </div>

  <input type="radio" name="bottom-tabs" class="tab" aria-label="Explore">
  <div class="tab-content pb-4">
    <p>Explore — discover trending topics, creators, and recommended content.</p>
  </div>

  <input type="radio" name="bottom-tabs" class="tab" aria-label="Saved">
  <div class="tab-content pb-4">
    <p>Saved — articles and posts you bookmarked for later.</p>
  </div>
</div>

制表符对齐到末尾

tabs-end 将选项卡条推到容器的右侧(末尾),对于辅助导航或操作菜单很有用。

Weekly view — aggregated metrics for the past 7 days.
Monthly view — trend analysis over the past 30 days.
Yearly view — annual summary and year-over-year comparison.
html
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
<div class="tabs tabs-underline tabs-end">
  <input type="radio" name="end-tabs" class="tab" aria-label="Week" checked>
  <div class="tab-content pt-4">Weekly view — aggregated metrics for the past 7 days.</div>

  <input type="radio" name="end-tabs" class="tab" aria-label="Month">
  <div class="tab-content pt-4">Monthly view — trend analysis over the past 30 days.</div>

  <input type="radio" name="end-tabs" class="tab" aria-label="Year">
  <div class="tab-content pt-4">Yearly view — annual summary and year-over-year comparison.</div>
</div>

JavaScript 控制的选项卡

对于非无线电模式(例如锚链接、动态内容),请在 JavaScript 中将 tab-active 添加到所选选项卡。配对的 tab-content 通过 .tab-active + .tab-content 选择器显示。

Dashboard panel — visible because this tab has tab-active.
Reports panel.
Integrations panel.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
<div class="tabs tabs-box" id="js-tabs">
  <button class="tab tab-active" data-tab="0">Dashboard</button>
  <div class="tab-content pt-4">Dashboard panel — visible because this tab has <code>tab-active</code>.</div>

  <button class="tab" data-tab="1">Reports</button>
  <div class="tab-content pt-4">Reports panel.</div>

  <button class="tab" data-tab="2">Integrations</button>
  <div class="tab-content pt-4">Integrations panel.</div>
</div>

<script>
  document.querySelectorAll('#js-tabs .tab').forEach(tab => {
    tab.addEventListener('click', () => {
      document.querySelectorAll('#js-tabs .tab').forEach(t => t.classList.remove('tab-active'));
      tab.classList.add('tab-active');
    });
  });
</script>
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
import { useTabs } from 'frutjam/react'

export default function TabsDemo() {
  const tabs = useTabs(0)
  return (
    <div className="tabs tabs-box">
      <button {...tabs.tabProps(0)}>Dashboard</button>
      <div {...tabs.panelProps(0)} className="tab-content pt-4">Dashboard panel.</div>

      <button {...tabs.tabProps(1)}>Reports</button>
      <div {...tabs.panelProps(1)} className="tab-content pt-4">Reports panel.</div>

      <button {...tabs.tabProps(2)}>Integrations</button>
      <div {...tabs.panelProps(2)} className="tab-content pt-4">Integrations panel.</div>
    </div>
  )
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
<script setup>
import { ref } from 'vue'
const active = ref(0)
</script>

<template>
  <div class="tabs tabs-box">
    <button
      v-for="(label, i) in ['Dashboard', 'Reports', 'Integrations']"
      :key="i"
      class="tab"
      :class="{ 'tab-active': active === i }"
      :aria-selected="active === i"
      role="tab"
      @click="active = i"
    ></button>

    <div class="tab-content pt-4" :hidden="active !== 0">Dashboard panel.</div>
    <div class="tab-content pt-4" :hidden="active !== 1">Reports panel.</div>
    <div class="tab-content pt-4" :hidden="active !== 2">Integrations panel.</div>
  </div>
</template>
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
<script>
  let active = $state(0)
  const labels = ['Dashboard', 'Reports', 'Integrations']
</script>

<div class="tabs tabs-box">
  {#each labels as label, i}
    <button
      class="tab"
      class:tab-active={active === i}
      aria-selected={active === i}
      role="tab"
      onclick={() => active = i}
    >{label}</button>
    <div class="tab-content pt-4" hidden={active !== i}>{label} panel.</div>
  {/each}
</div>

使用 Claude Code、Cursor 或其他 AI 编辑器?

Cherry MCP 为您的 AI 编辑器按需提供准确的 选项卡 类名称和结构。不再有幻觉课程。

尝试Cherry MCP