---
title: "页面页眉和页脚"
description: "了解如何在 Tiptap Pages 扩展中调整页面页眉高度和页脚高度。"
canonical_url: "https://tiptap.zhcndoc.com/pages/core-concepts/page-header-footer"
---

# 页面页眉和页脚

了解如何在 Tiptap Pages 扩展中调整页面页眉高度和页脚高度。

页眉和页脚允许你在每一页的顶部和底部显示一致的内容。Pages 扩展支持静态文本、HTML 标记、通过占位符实现的动态页码、使用 JSONContent 的富文本格式、首页或奇偶页不同的页眉/页脚，以及通过双击页眉或页脚区域进行交互式编辑。

> **Imported from DOCX:**
>
> 当你使用 [DOCX 导入扩展](https://tiptap.zhcndoc.com/conversion/import/docx/editor-extension.md#headers--footers) 导入 `.docx` 文件时，文档中的页眉和页脚会自动应用到 Pages，包括首页不同以及奇偶页不同的变体。无需额外配置。

> **Interactive demo:** [PagesHeaderFooter](https://embed-pro.tiptap.dev/preview/Extensions/PagesHeaderFooter)

## 页眉内容

- 将在页面页眉中渲染的内容
- 默认值：`''` – 空字符串

### 初始配置（字符串）

```js
Pages.configure({
  header: 'Awesome Tiptap header', // 字符串！
})
```

### 初始配置（HTML）

```js
Pages.configure({
  header: () => '<bold>Awesome Tiptap header</bold>', // 返回 HTML 或字符串的函数！
})
```

当文档通过 [`ExportDocx` 编辑器扩展](https://tiptap.zhcndoc.com/conversion/export/docx/editor-extension.md) 导出为 `.docx` 时，每个 `{page}` / `{total}` 都会转换为可在 Word 中实时使用的 `PAGE` / `NUMPAGES` 字段，因此 Word 会在打印或重新分页时重新计算这些数字。

#### 重命名或禁用占位符

使用 `placeholders` 选项可以重命名内置标记，或完全关闭替换。支持三种形式：

```js
// 将 {total} 重命名为 {pages}（保留 {page} 可用）
Pages.configure({
  placeholders: { total: 'pages' },
  footer: 'Page {page} of {pages}',
})

// 重命名两个内置标记
Pages.configure({
  placeholders: { page: 'p', total: 'pages' },
  footer: '{p} / {pages}',
})

// 禁用替换；{page} 和 {total} 将按字面文本渲染
Pages.configure({
  placeholders: false,
  footer: 'Page {page} of {total}',
})
```

当你重命名内置标记时，原始标记名将不再被识别。替换只会作用于页眉/页脚内容；正文中包含的 `{page}` / `{total}` 始终会按字面文本保留。

> **DOCX 导入:**
>
> 当导入 Word 文件时，`PAGE` 和 `NUMPAGES` 字段会以与你当前 `placeholders` 配置匹配的文本标记形式返回：默认是 `{page}` / `{total}`，或者是你重命名后的名称。导入侧的连接会将你的注册表转发给转换服务，因此带有实时页码的 Word 文档在重新导出时会无缝回到实时字段，无需额外配置。请参阅 [DOCX 导入 → 页码字段](https://tiptap.zhcndoc.com/conversion/import/docx/editor-extension.md#page-number-fields) 以了解完整说明。

### JSONContent

```js
editor.commands.setHeader('我很棒的页眉') // 字符串！
// 或者
editor.commands.Header((page, total) => `${page} / ${total}`) // 返回 HTML 或字符串的函数！
```

### 页眉替换模板

当 `header` 属性使用字符串时，提供了两个便捷的模板替换：

- `{page}`：被替换为当前页码。
- `{total}`：被替换为文档的总页数。

`header` 属性也可以接受一个函数，传递相同的信息，这次通过函数参数提供：

```js
Pages.configure({
  header: {
    type: 'doc',
    content: [
      {
        type: 'paragraph',
        content: [{ type: 'text', text: 'Document Title', marks: [{ type: 'bold' }] }],
      },
    ],
  },
})
```

## 页眉高度

- 控制每页顶部页眉区域的高度。
- 默认值：`50`（像素）

两种方式都可以设置内容：

**使用 configure 的初始设置：**

```js
Pages.configure({
  header: '我的文档标题',
  footer: '第 {page} 页，共 {total} 页',
})
```

**使用 commands 的运行时更新：**

```js
// 编辑器初始化后更新页眉
editor.commands.setHeader('更新后的页眉')
```

## 页眉配置

### 默认页眉

`header` 选项设置每页页眉区域显示的内容。

**初始配置：**

```js
Pages.configure({
  headerHeight: 80, // 让页眉区域更高
})
```

### 页眉高度编辑命令

```js
editor.commands.setHeaderHeight(30) // 更小的页眉！
```

## 页脚内容

- 将在页面页脚中渲染的内容
- 默认值：`{page}` – 带有页码模板替换的字符串

### 初始配置（字符串）

```js
Pages.configure({
  footer: 'Awesome Tiptap footer', // 字符串！
})
```

**编辑器命令：**

```js
// 覆盖页眉上边距
editor.commands.setHeaderTopMargin(40)

// 清除覆盖并回退到当前格式的默认值
//（该格式顶部边距的 50%）
editor.commands.resetHeaderTopMargin()
```

> **输入校验:**
>
> `setHeaderTopMargin` 会拒绝负值和 `NaN`；在这些情况下，该命令会返回 `false` 并记录警告。

## 页脚配置

### 默认页脚

`footer` 选项设置每页页脚区域显示的内容。

**初始配置：**

```js
Pages.configure({
  footer: () => '<bold>Awesome Tiptap 页脚</bold>', // 返回 HTML 或字符串的函数！
})
```

### 页脚内容编辑命令

```js
editor.commands.setFooter('我的超棒页脚') // 字符串！
// 或者
editor.commands.setFooter((page, total) => `${page} / ${total}`) // 返回 HTML 或字符串的函数！
```

### 页脚替换模板

当 `footer` 属性使用字符串时，提供了两个便捷的模板替换：

- `{page}`：被替换为当前页码。
- `{total}`：被替换为文档的总页数。

`footer` 属性也可以接受一个函数，传递相同的信息，这次通过函数参数提供：

```js
Pages.configure({
  footer: (page, total) => `${page} / ${total}` // 示例，显示："1 / 10"
})
```

**编辑器命令：**

```js
// 覆盖页脚下边距
editor.commands.setFooterBottomMargin(40)

// 清除覆盖并回退到当前格式的默认值
//（该格式底部边距的 50%）
editor.commands.resetFooterBottomMargin()
```

> **输入验证:**
>
> `setFooterBottomMargin` 会拒绝负值和 `NaN`；在这些情况下，该命令会返回 `false` 并记录警告。

## 首页不同

```js
editor.commands.setFooterHeight(30) // 更小的页脚！
```

> **注意:**
>
> `setDifferentFirstPage()` 命令可同时启用首页不同的页眉和页脚，行为类似 Microsoft Word。

> **首页空白槽位:**
>
> 调用 `setDifferentFirstPage(true)` 并不会将默认页眉/页脚复制到首页槽位中。它会保持空白，与 Microsoft Word 的行为一致。若要预先填充首页页眉或页脚，可在启用该标志后调用 `setHeaderFirstPage` / `setFooterFirstPage`，或者在 `Pages.configure()` 中设置 `headerFirstPage` / `footerFirstPage`。

### 配置

```js
Pages.configure({
  header: '默认页眉',
  footer: '第 {page} 页',
  differentFirstPage: true,
  headerFirstPage: '标题页',
  footerFirstPage: '', // 首页无页脚
})
```

### 命令

```js
// 启用首页不同（同时影响页眉和页脚）
editor.commands.setDifferentFirstPage(true)

// 设置首页页眉和页脚内容
editor.commands.setHeaderFirstPage('欢迎使用我的文档')
editor.commands.setFooterFirstPage('')
```

## 奇偶页不同

启用奇数页（1、3、5……）和偶数页（2、4、6……）不同的页眉和/或页脚，类似于微软 Word 的“奇偶页不同”选项。

> **注意:**
>
> `setDifferentOddEven()` 命令可同时启用奇偶页不同的页眉和页脚，行为类似 Microsoft Word。

> **奇数槽在启用时继承默认值:**
>
> 当你调用 `setDifferentOddEven(true)` 时，如果奇数槽为空，现有的默认页眉/页脚内容会被复制到
> **奇数**槽中。这与 Microsoft Word 的连续性
> 行为一致：第 1、3、5……页会继续显示切换标志之前的内容，而
> 偶数槽会先保持为空，供你填入内容。如果你先关闭再重新开启该标志，之前输入到奇数槽中的内容会被保留（只有在奇数槽
> 为空时才会发生复制）。

### 配置

```js
Pages.configure({
  differentOddEven: true,
  headerOdd: '章节标题 – 奇数页',
  headerEven: '书名 – 偶数页',
  footerOdd: '第 {page} 页',
  footerEven: '第 {page} 页',
})
```

### 命令

```js
// 启用奇偶页不同（同时影响页眉和页脚）
editor.commands.setDifferentOddEven(true)

// 设置奇数页和偶数页页眉
editor.commands.setHeaderOdd('奇数页页眉')
editor.commands.setHeaderEven('偶数页页眉')

// 设置奇数页和偶数页页脚
editor.commands.setFooterOdd('第 {page} 页')
editor.commands.setFooterEven('第 {page} 页')
```

## 首页与奇偶页同时启用

当同时启用 `differentFirstPage` 和 `differentOddEven` 时，首页页眉/页脚优先于奇偶页设置，同时页 1 使用首页设置。

**优先顺序：**

1. 首页（如果启用了 `differentFirstPage`）- 适用于第 1 页
2. 奇偶页（如果启用了 `differentOddEven`）- 适用于第 2 页及之后
3. 默认页眉/页脚 - 后备（仅在该区域未启用 `differentFirstPage` 和 `differentOddEven` 时使用）

> **空的特定类型槽位会渲染为空:**
>
> 当启用 `differentFirstPage` 或 `differentOddEven` 时，对应的槽位对其覆盖的页面具有
> 最高优先级，即使为空也是如此。例如，启用
> `differentFirstPage: true` 且 `headerFirstPage` 为空时，第 1 页会渲染为空页眉（它
> **不会** 静默回退到默认页眉）。这与 Microsoft Word 和 Google
> Docs 一致。只有当相关标志（`differentFirstPage` 或 `differentOddEven`）为 **关闭** 时，才会使用默认页眉/页脚作为后备。

```js
Pages.configure({
  header: 'Default Header', // 后备
  differentFirstPage: true,
  headerFirstPage: 'Title Page', // 第 1 页
  differentOddEven: true,
  headerOdd: 'Odd Page Header', // 第 3、5、7 页……
  headerEven: 'Even Page Header', // 第 2、4、6 页……
})
```

## 可编辑的页眉和页脚

用户可以通过双击页眉或页脚直接编辑它们。这将打开一个功能完备的 Tiptap 编辑器，允许丰富文本编辑。

### 自定义扩展

页眉/页脚编辑器使用与你在主编辑器中配置的相同扩展。为了匹配 schema（这样相同的 mark、节点和表格行为都能在页眉和页脚中工作），请通过 `headerFooterExtensions` 传入 `ConvertKit` 和 `TableKit`：

```ts
import { ConvertKit } from '@tiptap-pro/extension-convert-kit'
import { TableKit } from '@tiptap-pro/extension-pages-tablekit'

Pages.configure({
  header: 'My header',
  headerFooterExtensions: [ConvertKit.configure({ table: false }), TableKit],
})
```

任何 Tiptap 扩展都可以通过 `headerFooterExtensions` 选项添加到页眉/页脚编辑器中。与主编辑器的扩展栈保持一致，可以让文档及其页眉页脚之间的 schema、键盘快捷键和渲染效果保持统一。

> **协作使用回调形式:**
>
> `headerFooterExtensions` 也接受一个 `(ctx) => Extensions` 回调，它会针对每个页眉/页脚子类型触发一次，并传入子编辑器应绑定到的 Y 字段名和 Y.Doc。配置协作功能时请使用这种形式。请参阅 [为 Pages 添加协作功能](https://tiptap.zhcndoc.com/pages/guides/collaboration-with-pages.md)。

### 活动编辑器状态

当用户双击页眉或页脚进行编辑时，扩展会通过存储暴露当前激活的编辑器。这使你能够构建与页眉/页脚编辑器配合使用的自定义工具栏。

**存储属性：**

- `activeEditor` – 当前打开的页眉或页脚编辑器对应的 Tiptap Editor 实例（或 `null`）
- `activeEditorType` – `'header'`、`'footer'` 或 `null`
- `activePageNumber` – 正在编辑的页码（或 `null`）
- `headerEditorOn` / `headerEditorOff` – 订阅/取消订阅页眉覆盖层内部 Tiptap 编辑器上的事件
- `footerEditorOn` / `footerEditorOff` – 订阅/取消订阅页脚覆盖层内部 Tiptap 编辑器上的事件

该扩展还会监听页眉和页脚内部编辑器发出的 `focus` 事件。当用户聚焦到已打开的页眉或页脚编辑器时，`activeEditor`、`activeEditorType` 和 `activePageNumber` 会从当前激活的覆盖层中刷新。

### 锁定页眉或页脚

将 `editableHeader` 或 `editableFooter` 设置为 `false`，即可在不提供双击编辑能力的情况下渲染页眉/页脚。锁定后，用户或代码都无法打开覆盖层：`cursor: pointer` 提示会被移除，`openHeaderEditor` / `openFooterEditor` 命令会返回 `false`，并且任何已打开的覆盖层都会关闭（从而恢复主编辑器的 `editable` 状态）。

```ts
Pages.configure({
  header: 'Page {page} of {total}',
  editableHeader: false, // 在编辑器创建时即锁定
})
```

可在运行时通过 `setHeaderEditable` / `setFooterEditable` 切换：

```ts
editor.commands.setHeaderEditable(false) // 锁定
editor.commands.setHeaderEditable(true) // 解锁

editor.commands.setFooterEditable(false)
editor.commands.setFooterEditable(true)
```

> **锁定不会隐藏内容:**
>
> 锁定时页眉和页脚仍会正常渲染；只是移除了行内编辑能力。如果你想清除内容，请使用 `setHeader('')` / `setFooter('')`。

### 监听页眉/页脚编辑器事件

页眉和页脚各自拥有独立的编辑器。你可以通过 `editor.storage.pages` 订阅这些编辑器的事件。

```tsx
import { useEffect, useState } from 'react'

function HeaderFooterStatus({ editor }) {
  const [activeEditorType, setActiveEditorType] = useState(null)
  const [activePageNumber, setActivePageNumber] = useState(null)

  useEffect(() => {
    if (!editor) return

    const syncActiveEditorState = () => {
      const { activeEditorType, activePageNumber } = editor.storage.pages
      setActiveEditorType(activeEditorType)
      setActivePageNumber(activePageNumber)
    }

    editor.storage.pages.headerEditorOn?.('focus', syncActiveEditorState)
    editor.storage.pages.footerEditorOn?.('focus', syncActiveEditorState)

    return () => {
      editor.storage.pages.headerEditorOff?.('focus', syncActiveEditorState)
      editor.storage.pages.footerEditorOff?.('focus', syncActiveEditorState)
    }
  }, [editor])

  if (!activeEditorType || !activePageNumber) {
    return <span>正在编辑文档</span>
  }

  return (
    <span>
      正在编辑第 {activePageNumber} 页的 {activeEditorType}
    </span>
  )
}
```

你也可以将相同的辅助方法用于其他 Tiptap 编辑器事件，例如 `update`、`selectionUpdate`、`blur` 或 `transaction`。

### 构建自定义工具栏

下面是一个 React 组件示例，它为主编辑器和页眉/页脚编辑器提供一个统一的工具栏：

```tsx
import { useEditor, useEditorState, EditorContent } from '@tiptap/react'
import { useEffect, useState } from 'react'

function DocumentEditor() {
  const [headerFooterEditor, setHeaderFooterEditor] = useState(null)
  const [activeEditorType, setActiveEditorType] = useState(null)
  const [activePageNumber, setActivePageNumber] = useState(null)

  const editor = useEditor({
    extensions: [
      ConvertKit.configure({ table: false }),
      TableKit,
      Pages.configure({
        header: '文档页眉',
        footer: '第 {page} 页',
      }),
    ],
  })

  // 监听页眉/页脚编辑器的激活变化
  useEffect(() => {
    if (!editor) return

    const syncActiveHeaderFooterEditor = () => {
      const { activeEditor, activeEditorType, activePageNumber } = editor.storage.pages
      setHeaderFooterEditor(activeEditor)
      setActiveEditorType(activeEditorType)
      setActivePageNumber(activePageNumber)
    }

    editor.on('update', syncActiveHeaderFooterEditor)
    editor.storage.pages.headerEditorOn?.('focus', syncActiveHeaderFooterEditor)
    editor.storage.pages.footerEditorOn?.('focus', syncActiveHeaderFooterEditor)

    return () => {
      editor.off('update', syncActiveHeaderFooterEditor)
      editor.storage.pages.headerEditorOff?.('focus', syncActiveHeaderFooterEditor)
      editor.storage.pages.footerEditorOff?.('focus', syncActiveHeaderFooterEditor)
    }
  }, [editor])

  // 使用激活的编辑器（页眉/页脚或主编辑器）
  const activeEditor = activeEditorType ? headerFooterEditor : editor

  const { isBoldActive } = useEditorState({
    editor: activeEditor,
    selector: ({ editor: e }) => ({
      isBoldActive: e?.isActive('bold') ?? false,
    }),
  })

  return (
    <div>
      <div className="toolbar">
        <span>
          编辑中：{' '}
          {activeEditorType && activePageNumber
            ? `${activeEditorType}（第 ${activePageNumber} 页）`
            : '文档'}
        </span>
        <button
          className={isBoldActive ? 'is-active' : ''}
          onClick={() => activeEditor?.chain().focus().toggleBold().run()}
        >
          加粗
        </button>
      </div>
      <EditorContent editor={editor} />
    </div>
  )
}
```

## 访问页眉和页脚内容

用户通过页眉或页脚编辑器修改内容后，内容会存储在扩展的存储区。这对于保存文档或导出为 DOCX 等格式非常有用。

### HTML 内容

访问编辑后的 HTML 内容：

```js
// 默认页眉/页脚
const headerHTML = editor.storage.pages.headerHTML
const footerHTML = editor.storage.pages.footerHTML

// 首页
const headerFirstPageHTML = editor.storage.pages.headerFirstPageHTML
const footerFirstPageHTML = editor.storage.pages.footerFirstPageHTML

// 奇偶页
const headerOddHTML = editor.storage.pages.headerOddHTML
const headerEvenHTML = editor.storage.pages.headerEvenHTML
const footerOddHTML = editor.storage.pages.footerOddHTML
const footerEvenHTML = editor.storage.pages.footerEvenHTML
```

> **注意:**
>
> 这些存储值在用户通过相应的页眉/页脚编辑器编辑内容之前均为 `null`。编辑之前，使用配置中的原始模板。

### 用于 DOCX 导出的 JSON 内容

对于 DOCX 导出，使用 JSON 版本，它们提供结构化的 Tiptap 文档格式：

```js
// 默认页眉/页脚
const headerJSON = editor.storage.pages.headerJSON
const footerJSON = editor.storage.pages.footerJSON

// 首页
const headerFirstPageJSON = editor.storage.pages.headerFirstPageJSON
const footerFirstPageJSON = editor.storage.pages.footerFirstPageJSON

// 奇偶页
const headerOddJSON = editor.storage.pages.headerOddJSON
const headerEvenJSON = editor.storage.pages.headerEvenJSON
const footerOddJSON = editor.storage.pages.footerOddJSON
const footerEvenJSON = editor.storage.pages.footerEvenJSON
```

> **注意:**
>
> 这些存储值在用户通过相应的页眉/页脚编辑器编辑内容之前均为 `null`。编辑之前，使用配置中的原始模板。

### 保存页眉和页脚内容

保存页眉和页脚内容是你的责任。保存文档时从存储区获取内容，加载时再恢复。

**保存所有页眉和页脚内容：**

```js
function getHeaderFooterContent(editor) {
  const { pages } = editor.storage

  return {
    // 默认页眉/页脚
    headerHTML: pages.headerHTML,
    headerJSON: pages.headerJSON,
    footerHTML: pages.footerHTML,
    footerJSON: pages.footerJSON,

    // 首页
    headerFirstPageHTML: pages.headerFirstPageHTML,
    headerFirstPageJSON: pages.headerFirstPageJSON,
    footerFirstPageHTML: pages.footerFirstPageHTML,
    footerFirstPageJSON: pages.footerFirstPageJSON,

    // 奇偶页
    headerOddHTML: pages.headerOddHTML,
    headerOddJSON: pages.headerOddJSON,
    headerEvenHTML: pages.headerEvenHTML,
    headerEvenJSON: pages.headerEvenJSON,
    footerOddHTML: pages.footerOddHTML,
    footerOddJSON: pages.footerOddJSON,
    footerEvenHTML: pages.footerEvenHTML,
    footerEvenJSON: pages.footerEvenJSON,
  }
}

// 保存到后端
const headerFooterData = getHeaderFooterContent(editor)
await saveDocument({ content: editor.getJSON(), headerFooter: headerFooterData })
```

## 编程式打开和关闭编辑器

你可以通过编程方式打开和关闭页眉和页脚编辑器。这对于集成自定义 UI 元素、构建导航界面或响应用户操作非常有用。

### 打开编辑器

使用 `openHeaderEditor` 和 `openFooterEditor` 命令为指定页面打开编辑器：

```js
// 打开第 1 页的页眉编辑器
editor.commands.openHeaderEditor({ pageNumber: 1 })

// 打开第 3 页的页脚编辑器
editor.commands.openFooterEditor({ pageNumber: 3 })
```

这些命令在成功打开编辑器时返回 `true`，页面不存在时返回 `false`。

> **注意:**
>
> 打开一个编辑器时会自动关闭之前打开的任何页眉或页脚编辑器。主文档编辑器在页眉或页脚编辑器打开时不可编辑。

**使用场景：**

- 构建页码导航 UI，让用户直接跳转编辑指定页的页眉或页脚
- 在工具栏中创建“跳转到页眉/页脚”按钮
- 实现快捷键打开页眉或页脚
- 响应外部事件时编程打开编辑器

**示例：页面导航组件**

```tsx
function PageNavigation({ editor }) {
  const pageCount = editor.storage.pages.getPageCount?.() ?? 1

  return (
    <div>
      {Array.from({ length: pageCount }, (_, i) => (
        <div key={i + 1}>
          <span>第 {i + 1} 页</span>
          <button onClick={() => editor.commands.openHeaderEditor({ pageNumber: i + 1 })}>
            编辑页眉
          </button>
          <button onClick={() => editor.commands.openFooterEditor({ pageNumber: i + 1 })}>
            编辑页脚
          </button>
        </div>
      ))}
    </div>
  )
}
```

### 关闭编辑器

使用关闭命令关闭页眉或页脚编辑器：

```js
// 关闭当前打开的任何编辑器
editor.commands.closeHeaderFooterEditors()

// 关闭特定编辑器
editor.commands.closeHeaderEditor()
editor.commands.closeFooterEditor()
```

## 防止双击关闭编辑器

默认情况下，在打开的页眉或页脚编辑器外双击会关闭编辑器。你可以使用回调选项防止此行为，这在有工具栏按钮或其他 UI 元素时很有用，避免用户双击时编辑器意外关闭。

### 配置

提供三种回调选项：

- `onDblClickHeaderFooterPreventClose` - 适用于页眉和页脚（回退）
- `onDblClickHeaderPreventClose` - 仅适用于页眉（优先于回退）
- `onDblClickFooterPreventClose` - 仅适用于页脚（优先于回退）

每个回调函数接收 `MouseEvent`，返回 `true` 表示阻止关闭，`false` 允许关闭。

**示例：点击工具栏时防止关闭**

```js
Pages.configure({
  header: '我的页眉',
  footer: '第 {page} 页',
  onDblClickHeaderFooterPreventClose: (event) => {
    // 如果点击在工具栏内，保持编辑器打开
    const toolbar = document.querySelector('.my-toolbar')
    return toolbar?.contains(event.target)
  },
})
```

**示例：对页眉和页脚采用不同行为**

```js
Pages.configure({
  header: '我的页眉',
  footer: '第 {page} 页',
  // 双击页眉外部永不关闭
  onDblClickHeaderPreventClose: () => true,
  // 仍允许双击页脚外部关闭
  onDblClickFooterPreventClose: () => false,
})
```

## 重点强调颜色

可以自定义页眉和页脚编辑器覆盖层的视觉样式，调整强调色包括：

- **光标颜色** — 编辑器中的文本光标颜色
- **工具栏边框** — 编辑工具栏的顶部边框（页眉）或底部边框（页脚）
- **标签背景** — “页眉” 或 “页脚” 标签背景色

### 配置

在扩展配置时设置强调色：

```js
Pages.configure({
  header: '我的页眉',
  footer: '第 {page} 页',
  // 同时设置页眉和页脚的颜色
  accentColor: '#3b82f6',
})
```

也可以分别设置页眉和页脚的强调色：

```js
Pages.configure({
  header: '我的页眉',
  footer: '第 {page} 页',
  headerAccentColor: '#3b82f6', // 页眉的蓝色
  footerAccentColor: '#10b981', // 页脚的绿色
})
```

### 运行时更新

使用命令动态修改强调色：

```js
// 同时更新页眉和页脚颜色
editor.commands.setAccentColor('#8b5cf6')

// 仅更新页眉颜色
editor.commands.setHeaderAccentColor('#3b82f6')

// 仅更新页脚颜色
editor.commands.setFooterAccentColor('#ef4444')
```

> **CSS 颜色值:**
>
> 强调色选项支持任何有效的 CSS 颜色值，包括十六进制（`#3b82f6`）、rgb（`rgb(59,
>   130, 246)`）、hsl（`hsl(217, 91%, 60%)`）、oklch 或 CSS 变量（`var(--primary-color)`）。

## 工具栏渐变

当你打开页眉或页脚覆盖层时出现的编辑工具栏，在其标签和关闭按钮后方会有一个细微的白色渐变淡出效果。可以使用 `toolbarGradient` 选项将其禁用，从而获得平坦、无渐变的工具栏：

```js
Pages.configure({
  header: '我的页眉',
  footer: '第 {page} 页',
  toolbarGradient: false, // 平坦工具栏；默认值为 true
})
```

这是一个全局文档设置：它同样适用于页眉、页脚、[脚注](https://tiptap.zhcndoc.com/pages/core-concepts/footnotes.md)和[尾注](https://tiptap.zhcndoc.com/pages/core-concepts/endnotes.md)编辑工具栏，使它们保持视觉一致。

## 限制

### 页眉和页脚编辑器样式

页眉/页脚编辑器使用内置样式。但你可以通过 `accentColor`、`headerAccentColor` 和 `footerAccentColor` 选项自定义强调色。

### 协作功能

页眉和页脚编辑器会与主文档一起参与协作。每个子类型（默认、首页、奇数页、偶数页）都会独立协作，`differentFirstPage` / `differentOddEven` 切换会在客户端之间同步，文档级页面几何信息（`pageFormat`、`pageGap`、`headerTopMargin`、`footerBottomMargin`）也会同步，因此远程调用 `setPageFormat` 或修改边距会在每个客户端上重新排版。要启用协作，请将 `headerFooterExtensions` 作为一个**回调**传入，为每个子编辑器附加 `Collaboration` 扩展；静态数组形式不会为子编辑器启用协作。完整设置流程请参见[为 Pages 添加协作](https://tiptap.zhcndoc.com/pages/guides/collaboration-with-pages.md)。

> **协作时省略页眉/页脚默认值:**
>
> 启用协作时，不要在 `Pages.configure()` 中传入 `header` / `footer` 默认值；当其他客户端清空内容后，
> 它们可能会重新出现。请不要保留这些默认值；如果你需要一个初始值，请在 provider 同步完成后，
> 通过 `editor.commands.setHeader(...)` 只设置一次。

页眉/页脚编辑器使用内置样式，但你可通过 `accentColor`、`headerAccentColor` 和 `footerAccentColor` 选项自定义强调色。

| Option                               | Type                                | Default         | Description                                                                                                                                       |
| ------------------------------------ | ----------------------------------- | --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| `header`                             | `string \| JSONContent`             | `''`            | 默认页眉内容                                                                                                                                            |
| `footer`                             | `string \| JSONContent`             | `''`            | 默认页脚内容                                                                                                                                            |
| `headerTopMargin`                    | `number`                            | 顶部边距的 50%       | 从页面顶部到页眉内容的距离                                                                                                                                     |
| `footerBottomMargin`                 | `number`                            | 底部边距的 50%       | 从页脚内容到页面底部的距离                                                                                                                                     |
| `differentFirstPage`                 | `boolean`                           | `false`         | 启用不同的首页页眉和页脚                                                                                                                                      |
| `headerFirstPage`                    | `PagesHeaderFooter`                 | `''`            | 首页页眉内容                                                                                                                                            |
| `footerFirstPage`                    | `PagesHeaderFooter`                 | `''`            | 首页页脚内容                                                                                                                                            |
| `differentOddEven`                   | `boolean`                           | `false`         | 启用不同的奇数/偶数页页眉和页脚                                                                                                                                  |
| `headerOdd`                          | `PagesHeaderFooter`                 | `''`            | 奇数页页眉内容                                                                                                                                           |
| `headerEven`                         | `PagesHeaderFooter`                 | `''`            | 偶数页页眉内容                                                                                                                                           |
| `footerOdd`                          | `PagesHeaderFooter`                 | `''`            | 奇数页页脚内容                                                                                                                                           |
| `footerEven`                         | `PagesHeaderFooter`                 | `''`            | 偶数页页脚内容                                                                                                                                           |
| `editableHeader`                     | `boolean`                           | `true`          | 双击页眉时是否打开行内编辑器                                                                                                                                    |
| `editableFooter`                     | `boolean`                           | `true`          | 双击页脚时是否打开行内编辑器                                                                                                                                    |
| `headerFooterExtensions`             | `Extensions \| (ctx) => Extensions` | `ConvertKit`    | 页眉/页脚子编辑器的扩展。非协作模式请传入静态数组；如需为每个子类型附加 `Collaboration`，请传入回调。详见[为 Pages 添加协作](https://tiptap.zhcndoc.com/pages/guides/collaboration-with-pages.md)。 |
| `onDblClickHeaderFooterPreventClose` | `(event: MouseEvent) => boolean`    | `undefined`     | 回调：用于阻止在编辑器外双击时关闭页眉/页脚编辑器                                                                                                                         |
| `onDblClickHeaderPreventClose`       | `(event: MouseEvent) => boolean`    | `undefined`     | 回调：用于阻止在编辑器外双击时关闭页眉编辑器                                                                                                                            |
| `onDblClickFooterPreventClose`       | `(event: MouseEvent) => boolean`    | `undefined`     | 回调：用于阻止在编辑器外双击时关闭页脚编辑器                                                                                                                            |
| `accentColor`                        | `string`                            | `'#6366f1'`     | 页眉/页脚编辑器覆盖层的强调色                                                                                                                                   |
| `headerAccentColor`                  | `string`                            | `accentColor` 值 | 页眉编辑器覆盖层的强调色                                                                                                                                      |
| `footerAccentColor`                  | `string`                            | `accentColor` 值 | 页脚编辑器覆盖层的强调色                                                                                                                                      |
| `toolbarGradient`                    | `boolean`                           | `true`          | 是否显示编辑覆盖层工具栏后面的白色渐隐渐变（页眉、页脚、脚注、尾注）。`false` 表示使用纯色工具栏。                                                                                             |
| `placeholders`                       | `false \| { page?, total? }`        | `undefined`     | 重命名内置的 `{page}` / `{total}` 标记，或禁用替换。                                                                                                             |

页眉和页脚编辑不支持协作同步。它们分别是独立的 Tiptap 实例，与主文档的协作会话无关。

| 命令                         | 参数                          | 描述                                                                                     |
| -------------------------- | --------------------------- | -------------------------------------------------------------------------------------- |
| `setHeader`                | `header: PagesHeaderFooter` | 设置默认页眉内容                                                                               |
| `setFooter`                | `footer: PagesHeaderFooter` | 设置默认页脚内容                                                                               |
| `setHeaderTopMargin`       | `margin: number`            | 设置页眉上边距（像素）。拒绝负值和 `NaN`。                                                               |
| `resetHeaderTopMargin`     | none                        | 清除页眉上边距覆盖；回退到当前格式的默认值（格式顶部边距的 50%）。                                                    |
| `setFooterBottomMargin`    | `margin: number`            | 设置页脚下边距（像素）。拒绝负值和 `NaN`。                                                               |
| `resetFooterBottomMargin`  | none                        | 清除页脚下边距覆盖；回退到当前格式的默认值（格式底部边距的 50%）。                                                    |
| `setDifferentFirstPage`    | `enabled: boolean`          | 切换不同的首页（页眉 + 页脚）。首页槽位保持为空，与 Word 一致。如果页眉/页脚覆盖层已打开，则会刷新以显示新变体。                          |
| `setHeaderFirstPage`       | `header: PagesHeaderFooter` | 设置首页页眉内容                                                                               |
| `setFooterFirstPage`       | `footer: PagesHeaderFooter` | 设置首页页脚内容                                                                               |
| `setDifferentOddEven`      | `enabled: boolean`          | 切换不同的奇偶页（页眉 + 页脚）。启用时，会将默认页眉/页脚复制到奇数页槽位（如果为空），以保持与 Word 的连续性。如果页眉/页脚覆盖层已打开，则会刷新以显示新变体。 |
| `setHeaderOdd`             | `header: PagesHeaderFooter` | 设置奇数页页眉内容                                                                              |
| `setHeaderEven`            | `header: PagesHeaderFooter` | 设置偶数页页眉内容                                                                              |
| `setFooterOdd`             | `footer: PagesHeaderFooter` | 设置奇数页页脚内容                                                                              |
| `setFooterEven`            | `footer: PagesHeaderFooter` | 设置偶数页页脚内容                                                                              |
| `setHeaderEditable`        | `enabled: boolean`          | 锁定或解锁页眉覆盖层。为 `false` 时，双击无效，`openHeaderEditor` 返回 `false`，并关闭任何已打开的页眉覆盖层。              |
| `setFooterEditable`        | `enabled: boolean`          | 锁定或解锁页脚覆盖层。为 `false` 时，双击无效，`openFooterEditor` 返回 `false`，并关闭任何已打开的页脚覆盖层。              |
| `openHeaderEditor`         | `{ pageNumber: number }`    | 打开指定页面的页眉编辑器（从 1 开始计数）                                                                 |
| `openFooterEditor`         | `{ pageNumber: number }`    | 打开指定页面的页脚编辑器（从 1 开始计数）                                                                 |
| `closeHeaderFooterEditors` | none                        | 关闭当前打开的页眉/页脚编辑器                                                                        |
| `closeHeaderEditor`        | none                        | 如果页眉编辑器已打开则关闭它                                                                         |
| `closeFooterEditor`        | none                        | 如果页脚编辑器已打开则关闭它                                                                         |
| `setAccentColor`           | `color: string`             | 设置两个编辑器覆盖层的强调色                                                                         |
| `setHeaderAccentColor`     | `color: string`             | 设置页眉编辑器覆盖层的强调色                                                                         |
| `setFooterAccentColor`     | `color: string`             | 设置页脚编辑器覆盖层的强调色                                                                         |
