Skip to content

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

纯 HTML + CSS,零框架依赖,AI 友好