---
title: 侧栏导航 Sidebar
url: https://ui.zhaozimin.cn/patterns/sidebar/
markdown: https://ui.zhaozimin.cn/patterns/sidebar.md
group: 模式
origin: 展示版复刻（src/extracted），本仓库是唯一源头
source:
  - src/extracted/SidebarNav.jsx  # https://ui.zhaozimin.cn/src/extracted/SidebarNav.jsx
  - src/extracted/icons.jsx  # https://ui.zhaozimin.cn/src/extracted/icons.jsx
version: v0.2.0  # 设计系统版本，发布于 2026-09-23
scope: .zzm-v4   # 根节点必须带这个类，否则样式不生效
css: https://ui.zhaozimin.cn/v/0.2.0/zzm.css   # 锁版本地址，本仓库再改也不影响你
---

# 侧栏导航 Sidebar

> 纸色侧栏，宽 266。导航行是扁平的，不是键——当前行只加一层 .07 灰底和 600 字重；真正的操作（收起、退出）才用微拟物键。

### 样张 · 综合页侧栏

悬停导航行、名片、退出键试试

React：

```jsx
import { SidebarNav } from './extracted/SidebarNav.jsx'
import { ClockIcon, HomeIcon, MapIcon, PlayRectIcon, StarIcon } from './extracted/icons.jsx'

export function Hub() {
  return (
    <SidebarNav
      active="home"
      groups={[
        { items: [{ id: 'home', label: '首页', icon: <HomeIcon /> }] },
        { items: [
          { id: 'fav', label: '我的收藏', icon: <StarIcon />, count: 12 },
          { id: 'hist', label: '历史记录', icon: <ClockIcon />, count: 38 },
        ] },
      ]}
      user={{ name: '学员示例', email: 'learner@example.com' }}
    />
  )
}
```

HTML（构建时由上面的 React 渲染得到，可直接粘贴）：

```html
<aside
  style="
    width: 266px;
    height: 560px;
    display: flex;
    flex-direction: column;
    background: #f6f6f4;
    border-right: 1px solid rgba(0, 0, 0, 0.07);
  "
>
  <div style="display: flex; align-items: center; gap: 10px; padding: 12px 14px">
    <button
      type="button"
      title="收起侧边栏"
      class="zzm-btn zzm-btn--ghost zzm-btn--sm zzm-btn--icon"
      style="flex: none"
    >
      <svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true">
        <rect
          x="1.5"
          y="2.5"
          width="13"
          height="11"
          rx="2.5"
          stroke="#6E6E6A"
          stroke-width="1.3"
        ></rect>
        <line x1="6" y1="2.5" x2="6" y2="13.5" stroke="#6E6E6A" stroke-width="1.3"></line>
      </svg>
    </button>
    <svg width="22" height="22" viewBox="0 0 24 24" aria-hidden="true">
      <path
        d="M4 16 L10 7 L15 12 L20 5"
        stroke="#161616"
        stroke-width="1.5"
        fill="none"
        stroke-linecap="round"
      ></path>
      <circle cx="4" cy="16" r="2" fill="#161616"></circle>
      <circle cx="10" cy="7" r="2" fill="#161616"></circle>
      <circle cx="15" cy="12" r="2.4" fill="var(--zzm-accent,#A6402F)"></circle>
      <circle cx="20" cy="5" r="2" fill="#161616"></circle>
    </svg>
    <div style="flex: 1; font-size: 15px; font-weight: 650; letter-spacing: 0.3px">赵子民</div>
  </div>
  <nav style="padding: 2px 12px; display: flex; flex-direction: column; gap: 2px">
    <button
      type="button"
      class="zzm-navbtn"
      style="
        display: flex;
        align-items: center;
        gap: 10px;
        padding: 9px 10px;
        border: 0;
        border-radius: 8px;
        cursor: pointer;
        text-align: left;
        font-size: 13.5px;
        font-weight: 600;
        width: 100%;
        color: #26261f;
        background: rgba(0, 0, 0, 0.07);
        font-family: inherit;
      "
      aria-current="page"
    >
      <svg width="15" height="15" viewBox="0 0 16 16" fill="none" aria-hidden="true">
        <path
          d="M2.5 7.5 L8 2.5 L13.5 7.5"
          stroke="#3A3A36"
          stroke-width="1.4"
          fill="none"
          stroke-linecap="round"
          stroke-linejoin="round"
        ></path>
        <path
          d="M4 7 L4 13.5 L12 13.5 L12 7"
          stroke="#3A3A36"
          stroke-width="1.4"
          fill="none"
          stroke-linecap="round"
          stroke-linejoin="round"
        ></path>
      </svg>
      首页
    </button>
  </nav>
  <nav style="padding: 2px 12px; display: flex; flex-direction: column; gap: 2px">
    <button
      type="button"
      class="zzm-navbtn"
      style="
        display: flex;
        align-items: center;
        gap: 10px;
        padding: 9px 10px;
        border: 0;
        border-radius: 8px;
        cursor: pointer;
        text-align: left;
        font-size: 13.5px;
        font-weight: 450;
        width: 100%;
        color: #26261f;
        background: transparent;
        font-family: inherit;
      "
    >
      <svg width="15" height="15" viewBox="0 0 16 16" fill="none" aria-hidden="true">
        <path
          d="M8 2.2 L9.7 5.8 L13.6 6.3 L10.8 9 L11.5 12.9 L8 11 L4.5 12.9 L5.2 9 L2.4 6.3 L6.3 5.8 Z"
          stroke="#3A3A36"
          stroke-width="1.3"
          fill="none"
          stroke-linejoin="round"
        ></path>
      </svg>
      我的收藏
      <span style="flex: 1"></span>
      <span
        style="font-family:ui-monospace,&#x27;SF Mono&#x27;,Menlo,monospace;font-size:9.5px;color:#B0B0AA"
      >
        12
      </span>
    </button>
    <button
      type="button"
      class="zzm-navbtn"
      style="
        display: flex;
        align-items: center;
        gap: 10px;
        padding: 9px 10px;
        border: 0;
        border-radius: 8px;
        cursor: pointer;
        text-align: left;
        font-size: 13.5px;
        font-weight: 450;
        width: 100%;
        color: #26261f;
        background: transparent;
        font-family: inherit;
      "
    >
      <svg width="15" height="15" viewBox="0 0 16 16" fill="none" aria-hidden="true">
        <circle cx="8" cy="8" r="5.6" stroke="#3A3A36" stroke-width="1.3"></circle>
        <path
          d="M8 5.2 L8 8.2 L10.3 9.5"
          stroke="#3A3A36"
          stroke-width="1.3"
          fill="none"
          stroke-linecap="round"
          stroke-linejoin="round"
        ></path>
      </svg>
      历史记录
      <span style="flex: 1"></span>
      <span
        style="font-family:ui-monospace,&#x27;SF Mono&#x27;,Menlo,monospace;font-size:9.5px;color:#B0B0AA"
      >
        38
      </span>
    </button>
  </nav>
  <div style="flex: 1"></div>
  <div style="padding: 10px 12px 14px; border-top: 1px solid rgba(0, 0, 0, 0.07)">
    <div
      class="zzm-userfoot"
      style="
        padding: 10px 10px 11px;
        border-radius: 12px;
        cursor: pointer;
        border: 1px solid transparent;
        transition: background 0.15s ease;
      "
    >
      <div style="display: flex; align-items: center; gap: 10px">
        <span
          style="
            width: 36px;
            height: 36px;
            border-radius: 50%;
            background: #1d1d1b;
            color: #ffffff;
            display: flex;
            align-items: center;
            justify-content: center;
            font-size: 14px;
            font-weight: 650;
            flex: none;
          "
        >
          学
        </span>
        <span style="flex: 1; min-width: 0">
          <span style="display: block; font-size: 13px; font-weight: 600; color: #26261f">
            学员示例
          </span>
          <span
            style="
              display: block;
              margin-top: 1px;
              font-size: 10.5px;
              color: #a2a29c;
              overflow: hidden;
              text-overflow: ellipsis;
              white-space: nowrap;
            "
          >
            learner@example.com
          </span>
        </span>
        <svg
          width="11"
          height="11"
          viewBox="0 0 16 16"
          fill="none"
          aria-hidden="true"
          style="opacity: 0.4"
        >
          <path
            d="M6 3.5 L10.5 8 L6 12.5"
            stroke="#3A3A36"
            stroke-width="1.5"
            fill="none"
            stroke-linecap="round"
            stroke-linejoin="round"
          ></path>
        </svg>
      </div>
    </div>
    <button type="button" class="zzm-btn zzm-btn--block" style="margin-top: 6px">
      <svg width="12" height="12" viewBox="0 0 16 16" fill="none" aria-hidden="true">
        <path
          d="M6 2.5 L3 2.5 L3 13.5 L6 13.5"
          stroke="#8B8B85"
          stroke-width="1.4"
          fill="none"
          stroke-linecap="round"
        ></path>
        <path
          d="M7 8 L13.5 8 M11 5.5 L13.5 8 L11 10.5"
          stroke="#8B8B85"
          stroke-width="1.4"
          fill="none"
          stroke-linecap="round"
          stroke-linejoin="round"
        ></path>
      </svg>
      退出登录
    </button>
  </div>
</aside>
```

### 样张 · 课程页侧栏

分组标签：mono 10 · 字距 1.5 · #A2A29C

React：

```jsx
import { SidebarNav } from './extracted/SidebarNav.jsx'
import { ClockIcon, HomeIcon, MapIcon, PlayRectIcon, StarIcon } from './extracted/icons.jsx'

export function Course() {
  return (
    <SidebarNav
      active="map"
      groups={[
        { items: [
          { id: 'map', label: '学习地图', icon: <MapIcon /> },
          { id: 'ovw', label: '课程总览', icon: <PlayRectIcon /> },
        ] },
        { label: '主线课程', items: [
          { id: 's1', label: '软件基础', count: 5 },
          { id: 's2', label: '插件教学', count: 4 },
          { id: 's3', label: '笔记系统', count: 4 },
        ] },
        { label: '增值课程', items: [{ id: 's4', label: '人脉管理', count: 3 }] },
      ]}
    />
  )
}
```

HTML（构建时由上面的 React 渲染得到，可直接粘贴）：

```html
<aside
  style="
    width: 266px;
    height: 560px;
    display: flex;
    flex-direction: column;
    background: #f6f6f4;
    border-right: 1px solid rgba(0, 0, 0, 0.07);
  "
>
  <div style="display: flex; align-items: center; gap: 10px; padding: 12px 14px">
    <button
      type="button"
      title="收起侧边栏"
      class="zzm-btn zzm-btn--ghost zzm-btn--sm zzm-btn--icon"
      style="flex: none"
    >
      <svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true">
        <rect
          x="1.5"
          y="2.5"
          width="13"
          height="11"
          rx="2.5"
          stroke="#6E6E6A"
          stroke-width="1.3"
        ></rect>
        <line x1="6" y1="2.5" x2="6" y2="13.5" stroke="#6E6E6A" stroke-width="1.3"></line>
      </svg>
    </button>
    <svg width="22" height="22" viewBox="0 0 24 24" aria-hidden="true">
      <path
        d="M4 16 L10 7 L15 12 L20 5"
        stroke="#161616"
        stroke-width="1.5"
        fill="none"
        stroke-linecap="round"
      ></path>
      <circle cx="4" cy="16" r="2" fill="#161616"></circle>
      <circle cx="10" cy="7" r="2" fill="#161616"></circle>
      <circle cx="15" cy="12" r="2.4" fill="var(--zzm-accent,#A6402F)"></circle>
      <circle cx="20" cy="5" r="2" fill="#161616"></circle>
    </svg>
    <div style="flex: 1; font-size: 15px; font-weight: 650; letter-spacing: 0.3px">赵子民</div>
  </div>
  <nav style="padding: 2px 12px; display: flex; flex-direction: column; gap: 2px">
    <button
      type="button"
      class="zzm-navbtn"
      style="
        display: flex;
        align-items: center;
        gap: 10px;
        padding: 9px 10px;
        border: 0;
        border-radius: 8px;
        cursor: pointer;
        text-align: left;
        font-size: 13.5px;
        font-weight: 600;
        width: 100%;
        color: #26261f;
        background: rgba(0, 0, 0, 0.07);
        font-family: inherit;
      "
      aria-current="page"
    >
      <svg width="15" height="15" viewBox="0 0 16 16" fill="none" aria-hidden="true">
        <path
          d="M2.5 12.5 L6.5 4.5 L9.5 8.5 L13.5 3"
          stroke="#3A3A36"
          stroke-width="1.4"
          stroke-linecap="round"
          fill="none"
        ></path>
        <circle cx="9.5" cy="8.5" r="1.6" fill="var(--zzm-accent,#A6402F)"></circle>
      </svg>
      学习地图
    </button>
    <button
      type="button"
      class="zzm-navbtn"
      style="
        display: flex;
        align-items: center;
        gap: 10px;
        padding: 9px 10px;
        border: 0;
        border-radius: 8px;
        cursor: pointer;
        text-align: left;
        font-size: 13.5px;
        font-weight: 450;
        width: 100%;
        color: #26261f;
        background: transparent;
        font-family: inherit;
      "
    >
      <svg width="15" height="15" viewBox="0 0 16 16" fill="none" aria-hidden="true">
        <rect
          x="2"
          y="2.5"
          width="12"
          height="8"
          rx="1.5"
          stroke="#3A3A36"
          stroke-width="1.4"
        ></rect>
        <path d="M7 5.4 L9.6 6.9 L7 8.4 Z" fill="#3A3A36"></path>
      </svg>
      课程总览
    </button>
  </nav>
  <nav style="padding: 2px 12px; display: flex; flex-direction: column; gap: 2px">
    <div
      style="padding:12px 10px 4px;font-family:ui-monospace,&#x27;SF Mono&#x27;,Menlo,monospace;font-size:10px;letter-spacing:1.5px;color:#A2A29C"
    >
      主线课程
    </div>
    <button
      type="button"
      class="zzm-navbtn"
      style="
        display: flex;
        align-items: center;
        gap: 10px;
        padding: 9px 10px;
        border: 0;
        border-radius: 8px;
        cursor: pointer;
        text-align: left;
        font-size: 13.5px;
        font-weight: 450;
        width: 100%;
        color: #26261f;
        background: transparent;
        font-family: inherit;
      "
    >
      软件基础
      <span style="flex: 1"></span>
      <span
        style="font-family:ui-monospace,&#x27;SF Mono&#x27;,Menlo,monospace;font-size:9.5px;color:#B0B0AA"
      >
        05
      </span>
    </button>
    <button
      type="button"
      class="zzm-navbtn"
      style="
        display: flex;
        align-items: center;
        gap: 10px;
        padding: 9px 10px;
        border: 0;
        border-radius: 8px;
        cursor: pointer;
        text-align: left;
        font-size: 13.5px;
        font-weight: 450;
        width: 100%;
        color: #26261f;
        background: transparent;
        font-family: inherit;
      "
    >
      插件教学
      <span style="flex: 1"></span>
      <span
        style="font-family:ui-monospace,&#x27;SF Mono&#x27;,Menlo,monospace;font-size:9.5px;color:#B0B0AA"
      >
        04
      </span>
    </button>
    <button
      type="button"
      class="zzm-navbtn"
      style="
        display: flex;
        align-items: center;
        gap: 10px;
        padding: 9px 10px;
        border: 0;
        border-radius: 8px;
        cursor: pointer;
        text-align: left;
        font-size: 13.5px;
        font-weight: 450;
        width: 100%;
        color: #26261f;
        background: transparent;
        font-family: inherit;
      "
    >
      笔记系统
      <span style="flex: 1"></span>
      <span
        style="font-family:ui-monospace,&#x27;SF Mono&#x27;,Menlo,monospace;font-size:9.5px;color:#B0B0AA"
      >
        04
      </span>
    </button>
  </nav>
  <nav style="padding: 2px 12px; display: flex; flex-direction: column; gap: 2px">
    <div
      style="padding:12px 10px 4px;font-family:ui-monospace,&#x27;SF Mono&#x27;,Menlo,monospace;font-size:10px;letter-spacing:1.5px;color:#A2A29C"
    >
      增值课程
    </div>
    <button
      type="button"
      class="zzm-navbtn"
      style="
        display: flex;
        align-items: center;
        gap: 10px;
        padding: 9px 10px;
        border: 0;
        border-radius: 8px;
        cursor: pointer;
        text-align: left;
        font-size: 13.5px;
        font-weight: 450;
        width: 100%;
        color: #26261f;
        background: transparent;
        font-family: inherit;
      "
    >
      人脉管理
      <span style="flex: 1"></span>
      <span
        style="font-family:ui-monospace,&#x27;SF Mono&#x27;,Menlo,monospace;font-size:9.5px;color:#B0B0AA"
      >
        03
      </span>
    </button>
  </nav>
  <div style="flex: 1"></div>
</aside>
```

## 规格

| 部位 | 规格 |
|---|---|
| 容器 | 宽 266 · 底 `#F6F6F4` · 右侧 .07 细线 · 进场 `zzmSlide .28s` |
| 头部 | 收起键（28 幽灵图标键，恒位左 14 / 上 12）+ 星座标 22 + 品牌名 15 / 650 |
| 导航行 | 内距 9 × 10 · 圆角 8 · 13.5px · 当前行 `.07` 灰底 + 600 · 悬停 `.zzm-navbtn` |
| 计数 | mono 9.5 · `#B0B0AA` · 两位补零 |
| 名片 | 36 圆形头像 · 名字 13 / 600 · 邮箱 10.5 灰 · 悬停 `.zzm-userfoot` |
| 退出 | `.zzm-btn --block` 纸键 |

## 铁律

- ✓ 要：导航行扁平，当前行灰底
- ✗ 不要：把导航行做成一排凸键
- ✓ 要：收起键展开态与收起态同一坐标，零位移
- ✗ 不要：用朱色标当前导航项——朱色留给内容里的「下一步」

## 本页用到的 CSS

按样张里出现的类名，从源文件原样裁出（完整版见 zzm.css）：

```css
/* tokens.css · 用到的令牌 */
:root {
  --zzm-accent: #A6402F;
}

/* base.css */

.zzm-v4 .zzm-navbtn:hover { background: rgba(0, 0, 0, .07) !important; }

.zzm-v4 .zzm-userfoot:hover { background: rgba(0, 0, 0, .045); border-color: rgba(0, 0, 0, .07) !important; }

/* controls.css */

.zzm-v4 .zzm-btn {
  -webkit-appearance: none;
  appearance: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  height: 36px;
  padding: 0 16px;
  font-family: inherit;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: .2px;
  white-space: nowrap;
  cursor: pointer;
  user-select: none;
  border-radius: 8px;                                   /* 圆角矩形——按钮禁胶囊 */
  border: 1px solid rgba(0, 0, 0, .14);
  color: #3F3F3B;
  background: linear-gradient(180deg, #FFFFFF 0%, #F2F2EF 100%);
  box-shadow:
    0 0 0 3px rgba(255, 255, 255, .55),                 /* ④ 反光光晕环 */
    0 1px 2px rgba(0, 0, 0, .09),                       /* ③ 近影 */
    0 2px 6px rgba(0, 0, 0, .06),                       /* ③ 远影 */
    inset 0 1px 0 rgba(255, 255, 255, .92),             /* ② 顶部反光 */
    inset 0 -1px 0 rgba(0, 0, 0, .05);                  /* ① 底缘收沉 */
  transition: box-shadow .16s ease, transform .16s ease, background .16s ease,
    border-color .16s ease, filter .16s ease, opacity .16s ease;
}

.zzm-v4 .zzm-btn:hover {
  transform: translateY(-1px);
  border-color: rgba(0, 0, 0, .18);
  box-shadow:
    0 0 0 4px rgba(255, 255, 255, .8),
    0 2px 4px rgba(0, 0, 0, .10),
    0 4px 12px rgba(0, 0, 0, .09),
    inset 0 1px 0 rgba(255, 255, 255, .95),
    inset 0 -1px 0 rgba(0, 0, 0, .05);
}

.zzm-v4 .zzm-btn:active {
  transform: translateY(0);
  background: linear-gradient(180deg, #ECECE9 0%, #F4F4F1 100%);   /* ⑤ 凹面翻转 */
  box-shadow:
    0 0 0 3px rgba(255, 255, 255, .45),
    0 1px 0 rgba(255, 255, 255, .65),
    inset 0 2px 4px rgba(0, 0, 0, .13),
    inset 0 1px 2px rgba(0, 0, 0, .09);
}

.zzm-v4 .zzm-btn:focus-visible {
  outline: none;
  box-shadow:
    0 0 0 3px rgba(166, 64, 47, .20),                   /* 键盘焦点＝朱色光晕 */
    0 1px 2px rgba(0, 0, 0, .09),
    0 2px 6px rgba(0, 0, 0, .06),
    inset 0 1px 0 rgba(255, 255, 255, .92);
}

.zzm-v4 .zzm-btn:disabled {
  cursor: not-allowed;
  transform: none;
}

.zzm-v4 .zzm-btn:disabled:not(.zzm-btn--busy) {
  color: #A2A29C;
  background: #F2F2EF;
  border-color: rgba(0, 0, 0, .08);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .7), 0 1px 2px rgba(0, 0, 0, .04);
}

.zzm-v4 .zzm-btn--ghost {
  border-color: transparent;
  background: transparent;
  box-shadow: none;
  color: #4A4A46;
}

.zzm-v4 .zzm-btn--ghost:hover {
  transform: translateY(-1px);
  border-color: rgba(0, 0, 0, .14);
  background: linear-gradient(180deg, #FFFFFF 0%, #F2F2EF 100%);
  box-shadow:
    0 0 0 3px rgba(255, 255, 255, .55),
    0 1px 2px rgba(0, 0, 0, .09),
    0 2px 6px rgba(0, 0, 0, .06),
    inset 0 1px 0 rgba(255, 255, 255, .92);
}

.zzm-v4 .zzm-btn--ghost:active {
  transform: translateY(0);
  border-color: rgba(0, 0, 0, .14);
  background: linear-gradient(180deg, #ECECE9 0%, #F4F4F1 100%);
  box-shadow: inset 0 2px 4px rgba(0, 0, 0, .12);
}

.zzm-v4 .zzm-btn--sm { height: 28px; padding: 0 12px; font-size: 12px; gap: 4px; }

.zzm-v4 .zzm-btn--icon { width: 36px; padding: 0; }

.zzm-v4 .zzm-btn--icon.zzm-btn--sm { width: 28px; }

.zzm-v4 .zzm-btn--icon.zzm-btn--lg { width: 44px; }

.zzm-v4 .zzm-btn--block { width: 100%; }
```

---

上一页：[星图](https://ui.zhaozimin.cn/components/star-map.md) · 下一页：[数据表格](https://ui.zhaozimin.cn/patterns/data-table.md) · 全站目录：https://ui.zhaozimin.cn/llms.txt
