Tabs 标签页
实时预览
引入
html
<link rel="stylesheet" href="/tokens/tokens.css">
<link rel="stylesheet" href="/components/tabs/tabs.css">代码
HTML
html
<!-- Tabs Component — 标签切换组件,3种变体: default/pills/underline -->
<!-- Demo: Tabs 组件 -->
<div style="background: var(--color-bg-subtle); padding: 20px; border-radius: var(--radius-lg);">
<!-- 默认标签 -->
<div style="margin-bottom: 40px;">
<h3 style="margin-bottom: 16px; color: var(--color-text); font-size: var(--text-lg);">默认标签</h3>
<div class="tabs">
<div class="tabs__nav tabs__nav--default">
<button class="tabs__btn tabs__btn--active" data-tab="default-1">
<svg class="tabs__icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M3 9l9-7 9 7v11a2 2 0 01-2 2H5a2 2 0 01-2-2z"></path>
<polyline points="9,22 9,12 15,12 15,22"></polyline>
</svg>
概览
</button>
<button class="tabs__btn" data-tab="default-2">
<svg class="tabs__icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M14 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V8z"></path>
<polyline points="14,2 14,8 20,8"></polyline>
<line x1="16" y1="13" x2="8" y2="13"></line>
<line x1="16" y1="17" x2="8" y2="17"></line>
<polyline points="10,9 9,9 8,9"></polyline>
</svg>
详情
</button>
<button class="tabs__btn" data-tab="default-3">
<svg class="tabs__icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<circle cx="12" cy="12" r="3"></circle>
<path d="M19.4 15a1.65 1.65 0 00.33 1.82l.06.06a2 2 0 010 2.83 2 2 0 01-2.83 0l-.06-.06a1.65 1.65 0 00-1.82-.33 1.65 1.65 0 00-1 1.51V21a2 2 0 01-2 2 2 2 0 01-2-2v-.09A1.65 1.65 0 009 19.4a1.65 1.65 0 00-1.82.33l-.06.06a2 2 0 01-2.83 0 2 2 0 010-2.83l.06-.06a1.65 1.65 0 00.33-1.82 1.65 1.65 0 00-1.51-1H3a2 2 0 01-2-2 2 2 0 012-2h.09A1.65 1.65 0 004.6 9a1.65 1.65 0 00-.33-1.82l-.06-.06a2 2 0 010-2.83 2 2 0 012.83 0l.06.06a1.65 1.65 0 001.82.33H9a1.65 1.65 0 001-1.51V3a2 2 0 012-2 2 2 0 012 2v.09a1.65 1.65 0 001 1.51 1.65 1.65 0 001.82-.33l.06-.06a2 2 0 012.83 0 2 2 0 010 2.83l-.06.06a1.65 1.65 0 00-.33 1.82V9a1.65 1.65 0 001.51 1H21a2 2 0 012 2 2 2 0 01-2 2h-.09a1.65 1.65 0 00-1.51 1z"></path>
</svg>
设置
</button>
</div>
<div class="tabs__content">
<div class="tabs__panel tabs__panel--active" id="default-1">
<div style="padding: var(--space-6); background: var(--color-surface); border-radius: var(--radius-md); border: 1px solid var(--color-border);">
<h4 style="margin-bottom: var(--space-3); color: var(--color-text);">概览内容</h4>
<p style="color: var(--color-text-secondary); line-height: var(--leading-relaxed);">
这是默认标签的概览内容。标签组件提供了三种不同的视觉变体,适用于不同的使用场景。默认变体适合大多数情况,具有清晰的视觉层次。
</p>
</div>
</div>
<div class="tabs__panel" id="default-2">
<div style="padding: var(--space-6); background: var(--color-surface); border-radius: var(--radius-md); border: 1px solid var(--color-border);">
<h4 style="margin-bottom: var(--space-3); color: var(--color-text);">详情内容</h4>
<p style="color: var(--color-text-secondary); line-height: var(--leading-relaxed);">
这是详情标签的内容。每个标签面板都可以包含任何HTML内容,包括文本、图片、表单等。标签切换时会有平滑的动画效果。
</p>
</div>
</div>
<div class="tabs__panel" id="default-3">
<div style="padding: var(--space-6); background: var(--color-surface); border-radius: var(--radius-md); border: 1px solid var(--color-border);">
<h4 style="margin-bottom: var(--space-3); color: var(--color-text);">设置内容</h4>
<p style="color: var(--color-text-secondary); line-height: var(--leading-relaxed);">
这是设置标签的内容。标签组件支持禁用状态、图标、徽章等特性。可以根据需要灵活配置。
</p>
</div>
</div>
</div>
</div>
</div>
<!-- 胶囊标签 -->
<div style="margin-bottom: 40px;">
<h3 style="margin-bottom: 16px; color: var(--color-text); font-size: var(--text-lg);">胶囊标签</h3>
<div class="tabs">
<div class="tabs__nav tabs__nav--pills">
<button class="tabs__btn tabs__btn--active" data-tab="pills-1">
全部
<span class="tabs__badge">24</span>
</button>
<button class="tabs__btn" data-tab="pills-2">
进行中
<span class="tabs__badge">8</span>
</button>
<button class="tabs__btn" data-tab="pills-3">
已完成
<span class="tabs__badge">12</span>
</button>
<button class="tabs__btn tabs__btn--disabled" data-tab="pills-4">
已归档
</button>
</div>
<div class="tabs__content">
<div class="tabs__panel tabs__panel--active" id="pills-1">
<div style="padding: var(--space-6); background: var(--color-surface); border-radius: var(--radius-md); border: 1px solid var(--color-border);">
<h4 style="margin-bottom: var(--space-3); color: var(--color-text);">全部项目</h4>
<p style="color: var(--color-text-secondary); line-height: var(--leading-relaxed);">
显示所有项目,包括进行中、已完成和已归档的项目。胶囊变体适合用于筛选和分类场景。
</p>
</div>
</div>
<div class="tabs__panel" id="pills-2">
<div style="padding: var(--space-6); background: var(--color-surface); border-radius: var(--radius-md); border: 1px solid var(--color-border);">
<h4 style="margin-bottom: var(--space-3); color: var(--color-text);">进行中的项目</h4>
<p style="color: var(--color-text-secondary); line-height: var(--leading-relaxed);">
显示当前正在进行的项目。胶囊标签具有明显的视觉反馈,当前选中的标签会有背景色和阴影效果。
</p>
</div>
</div>
<div class="tabs__panel" id="pills-3">
<div style="padding: var(--space-6); background: var(--color-surface); border-radius: var(--radius-md); border: 1px solid var(--color-border);">
<h4 style="margin-bottom: var(--space-3); color: var(--color-text);">已完成的项目</h4>
<p style="color: var(--color-text-secondary); line-height: var(--leading-relaxed);">
显示已经完成的项目。每个标签可以显示徽章来表示项目数量,提供快速的信息概览。
</p>
</div>
</div>
<div class="tabs__panel" id="pills-4">
<div style="padding: var(--space-6); background: var(--color-surface); border-radius: var(--radius-md); border: 1px solid var(--color-border);">
<h4 style="margin-bottom: var(--space-3); color: var(--color-text);">已归档的项目</h4>
<p style="color: var(--color-text-secondary); line-height: var(--leading-relaxed);">
显示已归档的项目。禁用状态的标签无法点击,视觉上会有透明度降低的效果。
</p>
</div>
</div>
</div>
</div>
</div>
<!-- 下划线标签 -->
<div>
<h3 style="margin-bottom: 16px; color: var(--color-text); font-size: var(--text-lg);">下划线标签</h3>
<div class="tabs">
<div class="tabs__nav tabs__nav--underline">
<button class="tabs__btn tabs__btn--active" data-tab="underline-1">个人资料</button>
<button class="tabs__btn" data-tab="underline-2">安全设置</button>
<button class="tabs__btn" data-tab="underline-3">通知偏好</button>
<button class="tabs__btn" data-tab="underline-4">隐私设置</button>
</div>
<div class="tabs__content">
<div class="tabs__panel tabs__panel--active" id="underline-1">
<div style="padding: var(--space-6); background: var(--color-surface); border-radius: var(--radius-md); border: 1px solid var(--color-border);">
<h4 style="margin-bottom: var(--space-3); color: var(--color-text);">个人资料设置</h4>
<p style="color: var(--color-text-secondary); line-height: var(--leading-relaxed);">
管理您的个人资料信息,包括姓名、头像、联系方式等。下划线变体适合用于设置页面和表单导航。
</p>
</div>
</div>
<div class="tabs__panel" id="underline-2">
<div style="padding: var(--space-6); background: var(--color-surface); border-radius: var(--radius-md); border: 1px solid var(--color-border);">
<h4 style="margin-bottom: var(--space-3); color: var(--color-text);">安全设置</h4>
<p style="color: var(--color-text-secondary); line-height: var(--leading-relaxed);">
配置账户安全选项,包括密码修改、两步验证、登录历史等。下划线标签提供简洁的视觉效果。
</p>
</div>
</div>
<div class="tabs__panel" id="underline-3">
<div style="padding: var(--space-6); background: var(--color-surface); border-radius: var(--radius-md); border: 1px solid var(--color-border);">
<h4 style="margin-bottom: var(--space-3); color: var(--color-text);">通知偏好</h4>
<p style="color: var(--color-text-secondary); line-height: var(--leading-relaxed);">
设置您希望接收的通知类型和频率。下划线变体在切换时会有平滑的动画效果。
</p>
</div>
</div>
<div class="tabs__panel" id="underline-4">
<div style="padding: var(--space-6); background: var(--color-surface); border-radius: var(--radius-md); border: 1px solid var(--color-border);">
<h4 style="margin-bottom: var(--space-3); color: var(--color-text);">隐私设置</h4>
<p style="color: var(--color-text-secondary); line-height: var(--leading-relaxed);">
控制您的隐私选项,包括数据共享、可见性设置等。标签组件支持响应式设计,在移动设备上会有优化的显示效果。
</p>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- JavaScript 交互脚本 -->
<script>
// 标签切换功能
document.addEventListener('DOMContentLoaded', function() {
const tabsContainers = document.querySelectorAll('.tabs');
tabsContainers.forEach(container => {
const buttons = container.querySelectorAll('.tabs__btn');
const panels = container.querySelectorAll('.tabs__panel');
buttons.forEach(button => {
button.addEventListener('click', function() {
// 移除所有激活状态
buttons.forEach(btn => btn.classList.remove('tabs__btn--active'));
panels.forEach(panel => panel.classList.remove('tabs__panel--active'));
// 激活当前标签
this.classList.add('tabs__btn--active');
const targetId = this.getAttribute('data-tab');
const targetPanel = document.getElementById(targetId);
if (targetPanel) {
targetPanel.classList.add('tabs__panel--active');
}
});
});
});
});
</script>CSS
css
/* Tabs.css */
.tabs {
font-family: var(--font-sans);
}
/* ── 标签导航 ──────────────────────── */
.tabs__nav {
display: flex;
border-bottom: 1px solid var(--color-border);
position: relative;
}
/* ── 变体 ──────────────────────────── */
.tabs__nav--default {
gap: var(--space-1);
}
.tabs__nav--pills {
gap: var(--space-2);
background: var(--color-bg-muted);
padding: var(--space-1);
border-radius: var(--radius-md);
border-bottom: none;
}
.tabs__nav--underline {
gap: var(--space-8);
}
/* ── 标签按钮 ──────────────────────── */
.tabs__btn {
padding: var(--space-3) var(--space-4);
background: transparent;
border: none;
font-size: var(--text-sm);
font-weight: var(--weight-medium);
color: var(--color-text-secondary);
cursor: pointer;
transition: all var(--duration-fast) var(--ease-default);
position: relative;
white-space: nowrap;
}
.tabs__btn:hover {
color: var(--color-text);
}
.tabs__btn--active {
color: var(--color-primary);
}
/* ── 默认变体样式 ──────────────────── */
.tabs__nav--default .tabs__btn {
border-radius: var(--radius-md) var(--radius-md) 0 0;
}
.tabs__nav--default .tabs__btn--active {
background: var(--color-surface);
border-bottom: 2px solid var(--color-primary);
margin-bottom: -1px;
}
/* ── 胶囊变体样式 ──────────────────── */
.tabs__nav--pills .tabs__btn {
border-radius: var(--radius-md);
}
.tabs__nav--pills .tabs__btn--active {
background: var(--color-surface);
color: var(--color-primary);
box-shadow: var(--shadow-sm);
}
/* ── 下划线变体样式 ────────────────── */
.tabs__nav--underline .tabs__btn {
padding: var(--space-3) 0;
}
.tabs__nav--underline .tabs__btn--active {
color: var(--color-primary);
}
.tabs__nav--underline .tabs__btn--active::after {
content: '';
position: absolute;
bottom: -1px;
left: 0;
width: 100%;
height: 2px;
background: var(--color-primary);
}
/* ── 标签内容 ──────────────────────── */
.tabs__content {
padding: var(--space-6) 0;
}
.tabs__panel {
display: none;
animation: fadeIn var(--duration-normal) var(--ease-default);
}
.tabs__panel--active {
display: block;
}
@keyframes fadeIn {
from {
opacity: 0;
transform: translateY(10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
/* ── 标签图标 ──────────────────────── */
.tabs__icon {
width: 16px;
height: 16px;
margin-right: var(--space-2);
vertical-align: middle;
}
/* ── 标签徽章 ──────────────────────── */
.tabs__badge {
margin-left: var(--space-2);
padding: 2px 6px;
background: var(--color-primary-ghost);
color: var(--color-primary);
font-size: var(--text-xs);
font-weight: var(--weight-medium);
border-radius: var(--radius-full);
}
/* ── 响应式设计 ────────────────────── */
@media (max-width: 768px) {
.tabs__nav {
overflow-x: auto;
-webkit-overflow-scrolling: touch;
}
.tabs__nav--underline {
gap: var(--space-6);
}
.tabs__btn {
padding: var(--space-2) var(--space-3);
font-size: var(--text-xs);
}
}
/* ── 禁用状态 ──────────────────────── */
.tabs__btn--disabled {
opacity: 0.5;
cursor: not-allowed;
pointer-events: none;
}AI 使用说明
组件名: tabs
选择器: .tabs
依赖: /tokens/tokens.css
文件: /components/tabs/tabs.html