# 键盘导航

> 全部单键快捷键、它们何时让行给输入，以及按站点或按页面关闭的方法。

---

LLMS 索引： [llms.txt](/zh/llms.txt)

---

OINK 的交互式页面自带一套单键快捷键：WASD 在侧栏树中移动，J K 在标题间跳转，Q E 翻页，另有几个单键切换主题、语言与命令面板。默认开启，所有绑定都给输入让行，可以按站点或按页面关闭。

键盘导航不维护第二套状态：树的展开折叠复用侧栏原有的箭头按钮，逐节跳转读取右栏目录，切换语言与主题复用命令面板的同一批动作。键盘操作的顺序与鼠标操作的顺序因此一致。

## 侧栏 {#sidebar}

| 按键 | 行为 |
| --- | --- |
| W S ↑ ↓ | 焦点移到上一个 / 下一个可见项 |
| A D ← → | 折叠 / 展开分组；叶子节点上 A 跳到父级，D 无动作 |
| Enter Space G | 打开焦点所在的页面 |
| Esc | 退出树，焦点回到正文 |

四个字母键不需要先进入树：焦点还在正文时按 S，以当前页在侧栏里的那一项为起点下移一格并落焦。焦点行整行加深底色，比「当前页」的底色深一档，用于区分当前页与焦点位置。

窄屏侧栏收进抽屉、或桌面侧栏被折叠时，第一次按这四个键先展开侧栏。页面没有侧栏树时静默。

方向键 **只在焦点已经进入侧栏后** 才作用于树，正文里保持浏览器原生滚动。RTL 语言下 ← → 随阅读方向对调，A D 恒等于「折叠 / 展开」。

## 阅读 {#reading}

| 按键 | 行为 |
| --- | --- |
| J K | 沿页面目录跳到下一节 / 上一节 |
| N | 首页专用：跳到下一个顶层分区（首页 J 的助记别名） |
| Q E | 上一篇 / 下一篇 |
| H | 专注阅读模式：隐藏 / 恢复导航外壳 |

J K 的目标序列与右栏目录同源，落点与点击目录一致。跳转是固定 100 ms 的缓动滑行，与距离无关；连续按键不必等上一段动画结束。已经读到某一节内部一段距离后，K 先回到本节起点，再按一次才跳到上一节。页面没有标题时退化为一小段滑动。

Q E 按 **侧栏树的可视顺序** 翻页，不按日期。栏目入口页本身也是树里的一项，博客的栏目边界因此表现为「上一专栏最后一篇 → 下一专栏入口页 → 下一专栏第一篇」。折叠起来的分支不在这个顺序里：翻页顺序与焦点移动顺序是同一个。页面没有侧栏树时回退到页尾翻页器，没有翻页器时用 `<head>` 里的 `rel=prev/next`。

H 在首页只隐藏顶栏与页脚，在文档页同时隐藏左右栏与浮动按钮。状态记录在当前标签页的会话中，首帧之前恢复，用 Q E 连续翻页不丢状态、不闪烁。外壳隐藏时 WASD 不会把焦点送入不可见的侧栏。

## 外观、语言与路由 {#appearance}

| 按键 | 行为 |
| --- | --- |
| L Y | 循环切换语言（两个键等价） |
| T | 亮 / 暗模式切换 |
| R | 在首页与顶栏的同源一级入口之间循环 |

这三个键在任何交互式页面上都有效，不限于文档外壳。单语言站点的 L、关闭深浅色菜单后的 T、只有一个一级入口时的 R 都静默。R 只在同源的一级菜单项之间循环，外链与顶栏上的工具控件不参与。

## 搜索与命令 {#search}

| 按键 | 行为 |
| --- | --- |
| F 或 \/ | 打开命令面板的完整搜索态 |
| C 或反斜杠键 | 打开命令面板的纯命令态 |
| ⌘ + K 或 Ctrl + K | 打开面板；再按一次关闭 |

\/ 和反斜杠属于搜索功能本身，关闭键盘导航后仍然可用；F C 是键盘导航提供的别名，指向同一个面板实例。部分非美式键盘布局上反斜杠不易按到，在面板里输入 `>` 前缀同样进入纯命令态。面板里有什么见[命令面板](/zh/docs/customize/panel/)。

## 保留不占用的键 {#reserved}

\? 保留不绑定。速查卡挂在页脚最底层栏的问号按钮上，鼠标悬停、键盘聚焦或触摸都能打开，列出当前页面实际可用的按键：单语言站点看不到切换语言那一行。

G G、Shift + G 和数字键同样保留，可能用作将来的跳转序列。

## 快捷键的让行规则 {#stand-down}
所有绑定都是裸单键，凡是可能和输入或弹层冲突的场合一律禁用：

- 焦点在 input、textarea、select 或 `contenteditable` 区域里；
- 正在用输入法组字（中文站的硬约束）；
- 按住修饰键时：⌘ + C 仍是复制，Shift + ↓ 仍归浏览器；
- 命令面板或别的对话框开着，键盘归那个弹层。

评论区在 iframe 中，键事件不冒泡到页面，无需额外隔离。

## 焦点顺序与无障碍 {#a11y}

- **跳转链接**：进入页面后第一次按 Tab 出现的就是「跳转到主要内容」，一步跳过顶栏和侧栏。
- **真实焦点**：树内导航移动的是真正的 DOM 焦点，不是虚拟光标。屏幕阅读器因此读出链接名与「当前页」标记，Enter 是链接的原生行为，Tab 顺序没有被改写。
- **高对比度**：焦点行的底色在 `forced-colors` 模式下失效，退化为系统高亮色描边。
- **减弱动效**：`prefers-reduced-motion` 打开时，逐节跳转与翻页滚动改为瞬时定位，不做滑行。
- 速查卡里的键帽与正文里的[按键](/zh/docs/components/kbd/)组件是同一套样式。

## 关闭 {#disable}

全站关闭：

```yaml {title="hugo.yml"}
params:
  ui:
    keyboard_nav: false
```

单页关闭（交互密集的演示页常常需要），或者用 cascade 按整节关闭：

```yaml {title="content/docs/playground.zh.md"}
---
title: 交互演练场
keyboard_nav: false
---
```

这个键只接受布尔值，写成 `"false"` 或其它值时构建失败，报 `params.ui.keyboard_nav must be a boolean`。完整定义见[配置总览](/zh/docs/customize/config/)。

关闭后运行时不进入 JavaScript bundle，而不是加载后再判断。\/、反斜杠和 ⌘ + K 属于搜索，仍然可用；页脚折叠链接栅格的箭头不受影响。

## 验证 {#verify}

1. 构建后确认速查卡按钮在页面里：

   ```bash
   grep -c 'td-shell-keyboard__trigger' public/zh/docs/customize/keyboard/index.html
   ```

   关闭键盘导航且没开本地搜索时，这个按钮整个不生成。

2. 打开一篇文档，光标停在正文里连按 S：侧栏里应该从当前页那一项开始逐项下移，正文不动。

3. 按 E 若干次，核对翻页顺序与侧栏从上到下的顺序一致；折叠一个分组再翻，被折叠的页面应该被跳过。

4. 点进搜索框，按 J：页面 **不应该** 滚动，字符正常输入。使用中文输入法输入时同理。

5. 系统里打开「减弱动态效果」，再按 J：应该瞬间定位，没有滑行。

## 相关 {#related}

- [命令面板](/zh/docs/customize/panel/) — F C 打开的对话框
- [全文检索](/zh/docs/customize/search/) — 面板里页面结果的来源
- [布局与页面类型](/zh/docs/customize/layout/) — 哪些页面有侧栏与目录，决定哪些键有效
- [按键](/zh/docs/components/kbd/) — 在自己的文档里写键帽
- [配置总览](/zh/docs/customize/config/) — `ui.keyboard_nav` 的完整定义
