自定义编辑器样式

Tiptap 遵循无头优先(headless-first)方法,这意味着核心扩展不包含任何样式或 UI 组件——只有纯逻辑。这让你可以完全控制编辑器的外观和行为。

不过,我们现在也提供可选的 UI 组件和模板,帮助你加快开发速度。

Tiptap 的用户界面模板

想快速入门吗?

我们的 UI 模板包含常见编辑器功能的预构建组件。下载源代码并根据你的需求自定义。

构建你自己的 UI

如果你倾向于自己构建 UI,或者想了解 Tiptap 中的样式如何工作,下面是可用的方法。

使用普通 HTML 样式

整个编辑器是在一个带有类名 .tiptap 的容器中渲染的。你可以利用这一点,将样式应用到编辑器内容中:

/* 仅作用于编辑器 */
.tiptap p {
  margin: 1em 0;
}

使用 CSS 模块样式

CSS 模块 中,类名会被修改以实现局部作用域,这可能导致针对 .tiptap 类的样式无法生效。请使用全局样式或 :global(.tiptap) 修饰符来确保样式正确应用。

如果你在其他地方渲染存储的内容,可能不会有 .tiptap 容器,因此你可以在全局为相关的 HTML 标签添加样式:

/* 全局样式 */
p {
  margin: 1em 0;
}

添加自定义类

你可以完全控制渲染过程,包括向所有元素添加类。

扩展

大多数扩展允许你通过 HTMLAttributes 选项向渲染的 HTML 元素添加属性。你可以利用这一点添加自定义类(或其他属性)。当你使用 Tailwind CSS 时,这非常有用。

new Editor({
  extensions: [
    Document,
    Paragraph.configure({
      HTMLAttributes: {
        class: 'my-custom-paragraph',
      },
    }),
    Heading.configure({
      HTMLAttributes: {
        class: 'my-custom-heading',
      },
    }),
    Text,
  ],
})

渲染出的 HTML 如下:

<h1 class="my-custom-heading">示例文本</h1>
<p class="my-custom-paragraph">哇,这真是自定义的。</p>

如果扩展已经定义了类名,你添加的类会被追加。

编辑器

你甚至可以给包含编辑器的元素传递类:

new Editor({
  editorProps: {
    attributes: {
      class: 'prose prose-sm sm:prose lg:prose-lg xl:prose-2xl mx-auto focus:outline-none',
    },
  },
})

自定义 HTML

或者你可以自定义扩展的标记。以下示例将创建一个自定义粗体扩展,不渲染 <strong> 标签,而渲染 <b> 标签:

import Bold from '@tiptap/extension-bold'

const CustomBold = Bold.extend({
  renderHTML({ HTMLAttributes }) {
    // 原始:
    // return ['strong', HTMLAttributes, 0]
    return ['b', HTMLAttributes, 0]
  },
})

new Editor({
  extensions: [
    // …
    CustomBold,
  ],
})

你应该将自定义扩展放在单独的文件中,以便更好地组织,但你已经明白了。

使用 Tailwind CSS 样式

由于 Tiptap 中管理的内容是普通的 HTML,默认情况下没有 Tailwind CSS 类,你有几种方法可以为编辑器添加样式:

使用全局 CSS 文件和 @apply

尽管 Tailwind 官方不推荐大量使用 @apply,但我们认为它是为像 Tiptap 这类灵活的用户编辑内容定义样式的最佳方式。你可以在全局 CSS 文件里,对编辑器内的 HTML 标签应用 Tailwind 样式。由于嵌套选择器得到了广泛支持,你可以用 .tiptap 类限制作用范围:

.tiptap {
  p {
    @apply my-4 first:mt-0 last:mb-0 text-base leading-relaxed;
  }

  h1 {
    @apply text-3xl font-bold mt-8 mb-4 first:mt-0 last:mb-0;
  }
}

向扩展添加类

如果你不想使用全局 CSS 文件,更复杂的做法是扩展现有组件并在 renderHTMLHTMLAttributes 中添加 Tailwind 类。

import Paragraph from '@tiptap/extension-paragraph'

const TailwindParagraph = Paragraph.extend({
  renderHTML({ HTMLAttributes }) {
    return [
      'p',
      {
        ...HTMLAttributes,
        class: 'my-4 first:mt-0 last:mb-0 text-base leading-relaxed',
      },
      0,
    ]
  },
})

该方法可行,但随着更复杂的扩展或使用 NodeViews,会变得更加复杂,因此我们依然建议大多数情况下使用带 @apply 的全局 CSS 文件。

使用 @tailwindcss/typography 插件

编辑器同样兼容 Tailwind CSS。下面示例展示了使用 @tailwindcss/typography 插件样式的用法。

智能提示

如果你使用 TailwindCSS 智能提示,请将以下代码片段添加到你的 .vscode/settings.json 中,以启用对 Tiptap 对象内的智能提示支持:

"tailwindCSS.experimental.classRegex": [
  "class:\\s*?[\"'`]([^\"'`]*).*?,"
]

后续步骤