@fumadocs/tailwind 排版系统解析:基于 `--tw-prose-size` 的可缩放 Prose 排版
2026/9/15 12:05:51 网站建设 项目流程

@fumadocs/tailwind 排版系统解析:基于--tw-prose-size的可缩放 Prose 排版

【免费下载链接】fumadocsThe beautiful & flexible React.js docs framework.项目地址: https://gitcode.com/GitHub_Trending/fu/fumadocs

Fumadocs 是一个基于 React.js 构建的文档框架,其 UI 层围绕 Tailwind CSS 设计。@fumadocs/tailwind包正是「The Tailwind CSS utils for Fumadocs UI」——为 Fumadocs 文档渲染提供一套开箱即用的 Prose 排版工具链。本文围绕该包的版本演进核心(0.1.1引入的无单位--tw-prose-size可缩放排版、0.1.0的 Base UI 切换)以及其完整源码实现,讲解如何理解、配置并使用这套排版系统,读完后你将掌握在 Fumadocs 或任意 Tailwind CSS v4 项目中定制文档正文排版的能力。

包定位:Fumadocs 的排版工具包

@fumadocs/tailwind是一个独立的 npm 包,仅对外暴露两个入口,见 packages/tailwind/package.json:

{ "name": "@fumadocs/tailwind", "version": "0.1.1", "exports": { ".": "./dist/index.mjs", "./typography": "./dist/typography/index.mjs", "./package.json": "./package.json" } }
  • 主入口@fumadocs/tailwind目前为空实现(src/index.tsexport {}),用于包的基础占位;
  • 真正有价值的是@fumadocs/tailwind/typography子路径,它导出一个完整的 Tailwind CSS 插件,用于生成文档正文(prose)的排版样式。

从依赖关系看,该包将tailwindcss声明为peerDependencies^4.0.0,且为 optional),也就是说它面向 Tailwind CSS v4设计。构建产物由tsdown生成,构建配置见 packages/tailwind/tsdown.config.ts,其中将@fastify/deepmergepostcss-selector-parser等运行时依赖直接内联打包(onlyBundle),保证了插件安装后开箱即用、无需额外解析依赖。

核心机制一:无单位--tw-prose-size实现整体缩放

这是@fumadocs/tailwind@0.1.1引入的关键能力,也是 packages/tailwind/CHANGELOG.md 中描述的重头戏:

Scale prose typography with the unitless--tw-prose-sizevariable and add aprose-smmodifier for optically adjusted small text.

其设计思路是:不再像传统排版系统那样为每个字号硬编码固定像素值,而是把所有尺寸都包进一个calc(),乘上一个无单位的 CSS 自定义属性--tw-prose-size。这样只需改变这一个变量,整个文档正文的字体、间距、表格内边距等就会按比例整体缩放。

缩放工具函数的实现

在 packages/tailwind/src/typography/styles.ts 中,可以清楚看到这套缩放逻辑:

function scaled(value: string) { return `calc(${value} * var(--tw-prose-size))`; } function scaledPx(value: number) { return scaled(`${round(value)}px`); } function scaledRem(px: number) { return scaled(rem(px)); }
  • scaled()是核心:任意 CSS 值都会被包装为calc(<value> * var(--tw-prose-size))
  • scaledPx()用于像素值(如内边距),生成calc(3px * var(--tw-prose-size))
  • scaledRem()先将像素除以 16 换算为 rem,再参与缩放。

默认样式中的落地应用

DEFAULT配置(styles.ts#L141-L460)在根选择器上声明了基线:

'--tw-prose-size': '1', color: 'var(--tw-prose-body)', maxWidth: 'none', fontSize: calc(1rem * var(--tw-prose-size)), lineHeight: calc(1.75rem * var(--tw-prose-size)),

即默认--tw-prose-size: 1,所有尺寸保持原始比例。其余元素则大量引用缩放后的值,例如:

  • 标题h1使用scaled('var(--text-3xl)'),字号跟随设计令牌与缩放系数;
  • 行内代码codepaddingcalc(3px * var(--tw-prose-size))fontSizecalc(13px * var(--tw-prose-size))
  • 表格th/td的内边距为calc(var(--spacing) * 2.5 * var(--tw-prose-size))

值得注意的是,并非所有值都会被缩放border: solid 1pxborder-radius: 5px刻意保持不缩放。这一行为在 packages/tailwind/test/typography.test.ts 中有专门断言:

expect(css).toContain('border: solid 1px;'); expect(css).not.toContain('border: solid calc(1px * var(--tw-prose-size));'); expect(css).not.toContain('border-radius: calc(5px * var(--tw-prose-size));');

这体现了「视觉细节(边框、圆角)不随字号缩放,而间距与字号随排版缩放」的精细化设计哲学,避免小字号下边框和圆角显得过粗。

核心机制二:prose-sm修饰符与视觉微调

0.1.1同时新增了prose-sm修饰符,用于「optically adjusted small text」(光学调整的小号文本)。它并不是简单地等比例缩小,而是在缩小字号的同时做了字重上的视觉补偿。

SMALL配置在 packages/tailwind/src/typography/styles.ts:

export const SMALL: Config = { css: [ { '--tw-prose-size': '0.875', 'dt, strong, blockquote, h1, h2, h3, h4, kbd, thead th, a:not([data-card])': { fontWeight: '450', }, }, ], };

它做了两件事:

  1. --tw-prose-size设为0.875(即默认字号的 87.5%);
  2. 对标题、强调、引用、表格表头等原本字重较高的元素,统一收敛到font-weight: 450,以抵消小字号下的视觉「发胖」感,实现光学上的均衡。

对应测试 typography.test.ts 断言了该修饰符不会把粗体还原为 600/700/800/900:

expect(smallCss).toContain('font-weight: 450;'); expect(smallCss).not.toContain('font-weight: 600;');

用法上,proseprose-sm是同时挂在正文容器上的两个类:

<article class="prose prose-sm"> <!-- 文档正文 --> </article>

插件选项:自定义类名与圆角表格开关

插件入口位于 packages/tailwind/src/typography/index.ts,通过plugin.withOptions暴露两个配置项:

export interface Options { className?: string; /** * Disable custom table styles */ disableRoundedTable?: boolean; }

className:更换默认类名前缀

默认排版类名为prose,可通过className重命名。例如在 Tailwind CSS v4 配置中:

@plugin "@fumadocs/tailwind/typography" { className: "content"; }

测试 typography.test.ts 验证了自定义类名后content/content-sm生效、prose-sm不再生成。插件内部还通过prefix处理 Tailwind 的前缀配置,并用:where()not(:where([class~="not-prose"] ...))结构实现「not-prose白名单逃逸」,保证嵌套内容可以跳出排版样式。

disableRoundedTable:切换两种表格风格

styles.ts中内置了两套表格样式:

  • roundedTable(默认,styles.ts#L47-L84):使用border-collapse: separate+border-radius: var(--radius-lg),表头使用var(--color-fd-muted)背景、单元格带border-inline-start分隔线,契合 Fumadocs 卡片化设计语言;
  • normalTablestyles.ts#L86-L135):经典的分隔线表格,表头与行使用--tw-prose-th-borders/--tw-prose-td-borders变量控制边框色。

插件在addComponents阶段把对应表格样式合并进.prose类(见 index.ts):默认追加roundedTable,设置disableRoundedTable: true后切换为normalTable

与 Fumadocs 设计令牌的联动

整套排版颜色并不写死,而是通过 CSS 自定义属性映射到 Fumadocs 主题令牌(styles.ts),例如:

--tw-prose-body: color-mix(in oklab, var(--color-fd-foreground) 90%, transparent); --tw-prose-headings: var(--color-fd-foreground); --tw-prose-bullets: var(--color-fd-muted-foreground); --tw-prose-hr: var(--color-fd-border); --tw-prose-kbd-shadows: color-mix(in oklab, var(--color-fd-primary) 50%, transparent);

这意味着正文、标题、链接、引用、代码块、键盘键帽等颜色均自动跟随 Fumadocs 的--color-fd-*主题变量,无需任何额外配置即可适配浅色/深色主题。正文链接还会获得基于--color-fd-primary的强调色下划线(textUnderlineOffset: 3.5pxtextDecorationThickness: 1.5px),同时a:not([data-card])选择器保证链接卡片组件不受正文链接样式干扰。

DEFAULT配置还完整覆盖了列表、dl/dt/dd、引用块(含 open-quote/close-quote 引号)、ol[type="A" s]这类带s修饰的列表类型、picture图片、kbdfigure/figcaptionhr等文档场景,是一个结构完整的排版体系,而不只是简单的字号预设。

从版本历史理解演进方向

packages/tailwind/CHANGELOG.md 记录了这一排版能力的演进脉络:

版本关键变更
0.1.1引入无单位--tw-prose-size实现可缩放排版,新增prose-sm修饰符
0.1.0内部包与模板从 Radix UI 切换为 Base UI(影响 UI 层依赖,排版 API 不变)
0.0.5修复npm pack跳过嵌套node_modules的发布问题
0.0.4打包更多运行时依赖
0.0.3升级 Shiki.js v4(影响代码高亮相关样式生态)
0.0.2升级 tsdown 构建工具
0.0.1初始发布

从这些变更可以看到一个清晰的工程化思路:早期版本主要解决「打包与发布可靠性」问题(onlyBundle内联依赖、修复npm pack),随后转向「排版体验」的精细化(可缩放排版与prose-sm),同时跟随 Fumadocs 的 UI 基础设施演进(Base UI)。这也解释了为什么package.jsonpeerDependenciestailwindcss标记为可选——排版插件是渐进增强的,即便没有显式声明 tailwind 依赖,也能在宿主项目中正常参与编译。

安装与使用小结

在 Tailwind CSS v4 项目中启用该排版插件的方式:

pnpm add @fumadocs/tailwind

在全局样式中声明插件并可选传参:

@import "tailwindcss"; @plugin "@fumadocs/tailwind/typography";

然后在正文容器上使用:

<article class="prose prose-sm max-w-none"> <!-- 文档正文 --> </article>

如需自定义类名或切换表格风格,在@plugin中传参即可。验证编译结果可以复用包内测试所采用的 Tailwind CSS v4 官方compileAPI(见 typography.test.ts),它能在不启动完整构建的情况下快速断言生成的 CSS,是调试排版插件的有力手段。

总而言之,@fumadocs/tailwind以「一个 CSS 变量控制全局排版比例」为核心,配合prose-sm的光学微调、设计令牌联动与白名单逃逸机制,构成了 Fumadocs 文档正文排版的最小而完备的解决方案,其源码与测试也一并开放于仓库的 packages/tailwind 目录下,可作为 Tailwind CSS v4 插件开发的参考范本。

【免费下载链接】fumadocsThe beautiful & flexible React.js docs framework.项目地址: https://gitcode.com/GitHub_Trending/fu/fumadocs

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询