仅 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.
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-underline、tabs-box 或 tabs-lifted 更改选项卡条的视觉样式。
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 以匹配布局的密度。
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> |
带按钮的选项卡
将 tab 与 btn 结合起来,将选项卡呈现为样式按钮。 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.
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-disabled 和 disabled 属性以防止与选项卡交互。
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.
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.
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 将选项卡条推到容器的右侧(末尾),对于辅助导航或操作菜单很有用。
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 选择器显示。
tab-active.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 编辑器按需提供准确的 选项卡 类名称和结构。不再有幻觉课程。