对比效果
下面是使用 Tailwind CSS Typography 前后的对比效果。
- 左侧展示了未进行任何排版优化的原始
HTML,采用浏览器默认的User Agent Style。 - 右侧展示了应用
Typography默认的prose类后的效果:
H1:技术文档标题
H2:小节标题
H3:子小节标题
这是一个段落内容,用来演示浏览器默认样式。行高、字间距、段距等均未进行任何优化。
你可以写一些加粗、斜体或代码片段的文字。
这是一个引用区域。
- 无序列表项 A
- 无序列表项 B
- 有序列表 1
- 有序列表 2
function greet(name) {
return 'Hello, ' + name + '!';
}| 项目 | 说明 |
|---|---|
| HTML | 超文本标记语言 |
| CSS | 层叠样式表 |
H1:技术文档标题
H2:小节标题
H3:子小节标题
这是一个段落内容,用来演示Typography样式。行高、字间距、段距等均未进行任何优化。
你可以写一些加粗、斜体或代码片段的文字。
这是一个引用区域。
- 无序列表项 A
- 无序列表项 B
- 有序列表 1
- 有序列表 2
function greet(name) {
return 'Hello, ' + name + '!';
}| 项目 | 说明 |
|---|---|
| HTML | 超文本标记语言 |
| CSS | 层叠样式表 |
💡注意,仅仅增加了一个class=prose。
通过对比可见,Tailwind CSS Typography 插件(prose 类)在文本排版上带来了显著的视觉与可读性提升,包括:
- 更协调的字体大小与行高,提高阅读舒适度
- 恰当的段落与标题间距,使内容层次更清晰
- 更美观的列表样式(项目符号、缩进、行距)
- 统一优化的代码片段呈现(字体、背景、边距)
- 引用块、表格等元素的专业化排版处理
整体上,prose 帮助原始 HTML 内容实现了更具可读性与设计感的排版表现,适用于技术文档、博客文章等内容密集型页面。
初识 Typography 插件
如果你对刚才展示的排版效果感兴趣,接下来我们将深入了解这个插件的由来、作用与适用场景。
- 什么是
Typography? - 有什么用?
- 适用于什么场景?
- 适用人群?
近年来,Tailwind CSS 几乎成为现代前端项目的“默认选项”,不仅广泛应用于博客、文档、后台系统等场景,甚至像 OpenAI 等 AI 产品官网也采用了它。这样的趋势本身就值得我们了解一下它背后的设计理念与实际价值。
Tailwind CSS 是一个 “实用优先”(
utility-first)的 CSS 框架,它提供了大量原子级(单一职责)类名,用于直接在HTML中组合和构建复杂的用户界面,而无需编写传统意义上的CSS。 相比Bootstrap、Foundation等“组件化”框架,Tailwind不提供预设好的按钮、卡片、导航栏等组件,而是提供构建这些组件所需的低层级构建块(如text-center、bg-blue-500、p-4等类名)。
什么是Typography?
Tailwind CSS Typography 插件(也称为 @tailwindcss/typography 或 Prose 插件)是 Tailwind Labs 在2020年左右推出的一款官方插件,提出了 prose 概念,将一套富文本样式整合成可复用的类名。旨在为开发者提供“优雅、合理、语义化的富文本样式”,专门为HTML 中的长文内容(如文章、博客、Markdown 渲染输出等)预设的富文本样式集。
通过 prose 类名提供了一套默认的 typographic 样式(排版样式),用于美化和统一文章中的段落、标题、列表、代码块、引用、图片、表格等常见 HTML 元素的外观。
有什么用?
在原生 Tailwind 中或者直接手写CSS样式,虽然可以为任何 HTML 元素添加类来控制样式,但渲染结构复杂、层级深的富文本内容(如从 CMS 或 Markdown 渲染文章)会变得比较繁琐。
Typography 插件的核心用途是:
- 为未经自定义类名修饰的
HTML提供一致、美观的排版默认值 - 简化
Markdown或CMS输出内容的样式美化- 尤其适用于将
Markdown渲染为HTML的场景(如MDX、remark、rehype),可直接接管语义内容的样式渲染,无需手动标注类名。
- 尤其适用于将
- 提供“开箱即用”的优雅排版体验
- 通过可定制的主题,支持主题定制和深色模式
适用于什么场景?
✅ 非常适合
- 博客系统;
- 技术文档、知识库;
Markdown内容渲染页面(如Next.js的.mdx);- 新闻/文章展示页;
- 教育类内容平台;
Typography 插件虽然强大,但并不适用于所有页面类型:
🚫 不太适合
- 高度组件化、视觉自由度高的
UI模块; - 自定义结构、非标准语义内容(如复杂表单、图表交互);
适用人群
适合以下类型的用户:
初学者
- 能快速获得排版美观的页面,不需要逐个微调每个
HTML标签的样式;
中高级开发者
- 可自定义主题或通过插件扩展,实现符合设计系统的排版;
- 在构建内容平台、博客、静态站点时能大大节省工作量;
内容创作者/自媒体
- 配合
Headless CMS、Notion-to-blog等架构,直接套用生成文章样式;
那么,下一步就让我们真正“动手”,看看如何在项目中使用它,并了解它的基本配置与最佳实践。
Step-by-Step 使用教程
接下来的演示中,以 Next.js 为宿主框架,使用的版本为Tailwind CSS v4,即使你对 Next.js 不熟悉,也可以完全按照步骤操作,本地也可以运行,我们主要关注Typography的实际效果。
- 完整示例可查看 GitHub 仓库
- 在线演示查看 Github Pages Demo
先决条件:
- 本机安装了
Node.js 18.18及以上版本; - 安装
pnpm
创建应用
- 首先创建一个
next.js应用,采用pnpm作为包管理工具,这也是next.js官方推荐的方式,流程如下:
可选,如果网络不太好,通过如下方式使用
pnpm镜像服务器;
# 放心使用,只会对当前的终端起作用,不会影响全局
export NPM_CONFIG_REGISTRY=https://registry.npmmirror.com终端选择进入一个工程目录,输入如下命令:
npx create-next-app@latest --use-pnpm
# 如果本地没有安装会自动从 npm 注册表下载并安装最新版,
# 出现提示时,直接输入 `y` 确认
Need to install the following packages:
create-next-app@15.3.5
Ok to proceed? (y)create-next-app 会提示输入工程名称,以及选项确认,工程名称输入: tailwindcss-typography,其余都保持默认,注意code不要放到src目录中,避免后面的流程中路径不一致。默认会集成tailwindcss。
✔ What is your project named? … tailwindcss-typography
✔ Would you like to use TypeScript? … No / Yes
✔ Would you like to use ESLint? … No / Yes
✔ Would you like to use Tailwind CSS? … No / Yes
✔ Would you like your code inside a `src/` directory? … No / Yes
✔ Would you like to use App Router? (recommended) … No / Yes
✔ Would you like to use Turbopack for `next dev`? … No / Yes
✔ Would you like to customize the import alias (`@/*` by default)? … No / Yes
终端输入以下命令,进入刚刚创建的工程目录,这里,我们用tailwindcss-typography
cd tailwindcss-typography
- 安装
@tailwindcss/typography,我们输入以下命令安装typography插件
pnpm add -D @tailwindcss/typography使用你熟悉的编辑器 如:visual studio code 、cursor、windsurf、trae 等打开这个目录,查看package.json,在devDependencies部分应该有插件的信息,如下:
{
...
"devDependencies": {
...
"@tailwindcss/typography": "^0.5.16",
"tailwindcss": "^4",
...
}
}至此,初始化项目部分已经完成。
在后续的流程中,如果出现next.js、react、typescript等不熟悉的概念,不用担心,我们聚焦于typography的相关内容,脱离了这些, 换成javascript、vite、vue等,一样可以正常使用,关注的始终是typography的核心理念,以及如何使用的内容。
认识 prose
打开编辑器,完成下面两个操作:
- 编辑
app目录下的globals.css,在第二行,即:@import "tailwindcss";后面增加引入插件代码,如下:
@import "tailwindcss";
@plugin "@tailwindcss/typography";- 编辑
app目录下的page.tsx文件,将里面的内容全部删掉,替换成如下的代码:
import Link from "next/link"
export default function Home() {
return (
<div className="flex flex-row space-x-6 items-start justify-center h-screen w-screen p-8">
<div>
<h1>❌ 没用 Typography</h1>
<h2>H2:小节标题</h2>
<h3>H3:子小节标题</h3>
<p>没有使用 typography 样式,使用的是浏览器默认的样式,即:User Agent Stylesheet。</p>
<p>
你可以写一些<span style={{ fontWeight: "bold" }}>加粗</span>、<em>斜体</em>或<code>代码片段</code>的文字。
</p>
<blockquote>这是一个引用区域。</blockquote>
<ul>
<li>无序列表项 A</li>
<li>无序列表项 B</li>
</ul>
<ol>
<li>有序列表 1</li>
<li>有序列表 2</li>
</ol>
<pre>
<code>{`function greet(name) {
return 'Hello, ' + name + '!';
}`}</code>
</pre>
<table>
<thead>
<tr>
<th>项目</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td>HTML</td>
<td>超文本标记语言</td>
</tr>
<tr>
<td>CSS</td>
<td>层叠样式表</td>
</tr>
</tbody>
</table>
<h4>功能展示</h4>
<ul>
<li>
<Link href="/1-size-modifiers">Size Modifiers 内置字号调整工具</Link>
</li>
<li>
<Link href="/2-element-modifiers">Element Modifiers 个性化</Link>
</li>
<li>
<Link href="/3-tailwind-config-js">Tailwind Config JS 个性化</Link>
</li>
<li>
<Link href="/4-gray-scale">Gray Scale 灰度主题</Link>
</li>
<li>
<Link href="/5-override-max-width">覆盖默认最大宽度</Link>
</li>
<li>
<Link href="/6-undo-style">撤销prose样式</Link>
</li>
</ul>
</div>
<div className="prose dark:prose-invert">
<h1>✅ 使用 Typography</h1>
<h2>H2:小节标题</h2>
<h3>H3:子小节标题</h3>
<p>这是一个段落内容,用来演示 typography 样式。行高、字间距、段距等展示的视觉效果。</p>
<p>
你可以写一些<span style={{ fontWeight: "bold" }}>加粗</span>、<em>斜体</em>或<code>代码片段</code>的文字。
</p>
<blockquote>这是一个引用区域。</blockquote>
<ul>
<li>无序列表项 A</li>
<li>无序列表项 B</li>
</ul>
<ol>
<li>有序列表 1</li>
<li>有序列表 2</li>
</ol>
<pre>
<code>{`function greet(name) {
return 'Hello, ' + name + '!';
}`}</code>
</pre>
<table>
<thead>
<tr>
<th>项目</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td>HTML</td>
<td>超文本标记语言</td>
</tr>
<tr>
<td>CSS</td>
<td>层叠样式表</td>
</tr>
</tbody>
</table>
<h4>功能展示</h4>
<ul>
<li>
<Link href="/1-size-modifiers">Size Modifiers 内置字号调整工具</Link>
</li>
<li>
<Link href="/2-element-modifiers">Element Modifiers 个性化</Link>
</li>
<li>
<Link href="/3-tailwind-config-js">Tailwind Config JS 个性化</Link>
</li>
<li>
<Link href="/4-gray-scale">Gray Scale 灰度主题</Link>
</li>
<li>
<Link href="/5-override-max-width">覆盖默认最大宽度</Link>
</li>
<li>
<Link href="/6-undo-style">撤销prose样式</Link>
</li>
</ul>
</div>
</div>
)
}回到终端,在应用目录下,输入启动命令启动开发服务器,同时在浏览器中输入地址 http://localhost:3000,默认端口是3000。
pnpm dev
> tailwindcss-typography@0.1.0 dev /tailwindcss-typography
> next dev --turbopack
▲ Next.js 15.3.5 (Turbopack)
- Local: http://localhost:3000
- Network: http://192.168.5.35:3000打开浏览器后,你会看到左侧展示了浏览器的默认样式(User Agent Style),右侧是typography的样式效果,和最上面的对比效果一致。
如果你此时观察代码发现,抛开那些tailwindcss原子类flex flex-row space-x-6...不管,你会发现,两个div唯一的不同是:仅仅增加了一个class=prose。
<div>
...
</div>
<div class="prose">
...
</div>
接下来,我们来探究下发生了什么,以及Tailwind CSS和typography做了什么。
当在一个 HTML 元素上添加类名 prose 时,Tailwind CSS + @tailwindcss/typography 插件背后会做很多事。它并不像其他 Tailwind 原子类一样只应用一两个样式,而是注入了一整套针对“文章类内容”优化的排版样式。
prose 是一组预设的 “文章内容排版样式集合”,它通过设置嵌套元素(如 h1~h6、p、ul、ol、blockquote、code 等)的默认样式,让原始 HTML 呈现出更优雅、结构清晰、可读性强的排版效果。
从技术实现上,当安装typography插件并应用prose类后,Tailwind会扫描html、mdx、tsx等文件,若发现了prose类,就会把这一套排版样式编译进最终 CSS 文件中。
不像Tailwind原子类text-lg或text-blue-100等应用到单个元素上,prose 是一种 “作用于子元素的样式集”,会生成如下的内容:
.prose h1 { font-size: 2.25rem; font-weight: 800; line-height: 1.2; }
.prose p { margin-top: 1.25em; margin-bottom: 1.25em; }
.prose ul { padding-left: 1.5em; list-style-type: disc; }
.prose code { background-color: rgba(0,0,0,0.05); padding: 0.2em 0.4em; }
.prose blockquote { border-left: 0.25em solid #ccc; padding-left: 1em; color: #666; font-style: italic; }
/* ... 等数百行样式 */总之:在元素上加上 .prose,Tailwind Typography 插件就会帮你自动美化文章内容中常见的标签,比如段落、标题、列表、引用、代码、表格等,让它们在不写任何额外样式的情况下看起来就像博客、技术文档那样整洁清晰。
在使用responsive design(响应式设计)的时候,需要在<head>中增加:
<meta name="viewport" content="width=device-width, initial-scale=1.0" />为什么需要添加
<meta name=....?
meta标签的作用是告诉浏览器如何控制页面的视口(viewport):width=device-width: 将视口的宽度设置为设备自身的宽度。例如,在手机上,它会使页面的宽度与手机屏幕的物理宽度匹配。如果没有这一项,浏览器可能会默认将页面渲染成实际大小(例如980px),然后缩小以适应移动设备屏幕,这会导致文字过小、布局混乱。initial-scale=1.0: 设置页面首次加载时的缩放比例为1.0,即不进行任何缩放。结合width=device-width,这确保了页面的CSS像素与设备独立像素(device-independent pixels)之间是1:1的关系,从而使响应式设计能够按照预期工作。- 若没有
meta标签,浏览器无法正确识别设备的屏幕宽度, Tailwind CSS 响应式类(例如md:,lg:等)将无法按照预期在不同的屏幕尺寸上生效,因为浏览器不会触发正确的断点。
typography 还提供了5种开箱即用的排版响应式尺寸修饰符和灰度修饰类。我们来继续了解。
响应式尺寸修饰符
首先,要理解Tailwind CSS是移动优先(mobile-first)的策略,即:默认的样式是适用于最小视口(手机端),然后通过内置的breakpoint prefix(断点前缀),来覆盖更大屏幕的样式。通过该策略,可以实现响应式设计。
Tailwind CSS 内置了5个常用的断点:
| Breakpoint prefix | 最小 width | 对应的CSS |
|---|---|---|
sm | 40rem (640px) | @media (width >= 40rem) { ... } |
md | 48rem (768px) | @media (width >= 48rem) { ... } |
lg | 64rem (1024px) | @media (width >= 64rem) { ... } |
xl | 80rem (1280px) | @media (width >= 80rem) { ... } |
2xl | 96rem (1536px) | @media (width >= 96rem) { ... } |
断点的理解:当屏幕宽度达到某个宽度(1280px)时,应用对应排版风格,本质就是CSS的media query,也就是最基础的响应式设计。
相应的,typography也基于此,提供了5种不同尺寸的字体大小,size modifiers。
| Class | Body font size |
|---|---|
prose-sm | 0.875rem (14px) |
prose-base (default) | 1rem (16px) |
prose-lg | 1.125rem (18px) |
prose-xl | 1.25rem (20px) |
prose-2xl | 1.5rem (24px) |
可以配合breakpoing prefix或单独使用。
如:prose lg:prose-xl 意思是,默认使用prose(移动端,字体较小),当页面宽度≥1024px 时,通过size modifiers来整体增大字体,即: prose-xl。
⚠️,在添加尺寸修饰符时,始终需要包含prose类。
typography提供的尺寸调整参数由专业设计师精心手动调校,旨在呈现最完美的视觉效果,参数涵盖了字体大小之间的关系、标题间距、代码块内边距等多个方面,比起非设计专业的开发人员,要美观很多,即使不用,这些设计模式亦俱备参考价值。
可以查看插件的默认样式styles.js,深入查看每个修饰符的示例。
我们看下不同尺寸大小的效果。
在app目录下创建1-size-modifiers目录,在该目录下创建page.tsx文件,复制如下的代码:
export const metadata = {
title: "Size Modifiers",
description: "Size Modifiers",
}
export default function SizeModifiersPage() {
const generateHtmlCode = (title: string = "技术文档标题", subtitle: string = "小节标题") => {
return `
<h1>H1:${title}</h1>
<h2>H2:${subtitle}</h2>
<h3>H3:子小节标题</h3>
<p>Tailwind CSS 遵循的是移动优先的设计原则。这意味着:默认情况下不加任何修饰符(比如 text-blue-500 或 p-4)的 CSS 规则会应用于所有屏幕尺寸,包括最小的移动设备屏幕。当你使用像 sm:, md:, lg: 这样的断点前缀时,你是在为更大(或等于)的屏幕尺寸添加或覆盖样式。断点是累积和覆盖的。 如果你只使用了 sm: 而没有使用 md: 或 lg:,那么 sm: 的样式将从 640px 开始一直生效到无限大(或者直到被另一个断点样式覆盖)。</p>
<p>
你可以写一些<span style="font-weight: bold;">加粗</span>、<em>斜体</em>或<code>代码片段</code>的文字。
</p>
<blockquote>这是一个引用区域。</blockquote>
<ul>
<li>无序列表项 A</li>
<li>无序列表项 B</li>
</ul>
<ol>
<li>有序列表 1</li>
<li>有序列表 2</li>
</ol>
<pre><code>function greet(name) {
return 'Hello, ' + name + '!';
}</code>
</pre>
<table>
<thead>
<tr>
<th>项目</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td>HTML</td>
<td>超文本标记语言</td>
</tr>
<tr>
<td>CSS</td>
<td>层叠样式表</td>
</tr>
</tbody>
</table>`
}
const configurations = [
{ proseClass: "prose-sm", title: "prose-sm 0.875rem (14px)", subtitle: "适用于 640px 以上屏幕" },
{ proseClass: "prose-base", title: "prose-base 1rem (16px)", subtitle: "也可写成 prose,是默认规则,适用于 768px 以上屏幕" },
{ proseClass: "prose-lg", title: "prose-lg 1.125rem (18px)", subtitle: "适用于 1024px 以上屏幕" },
{ proseClass: "prose-xl", title: "prose-xl 1.25rem (20px)", subtitle: "适用于 1280px 以上屏幕" },
{ proseClass: "prose-2xl", title: "prose-2xl 1.5rem (24px)", subtitle: "适用于 1536px 以上屏幕" },
]
return (
<div className="flex flex-row space-x-4 p-3">
{configurations.map((config, index) => (
<div
key={index}
className={`w-1/5 border-1 border-gray-300 p-2 prose dark:prose-invert ${config.proseClass}`}
dangerouslySetInnerHTML={{
__html: generateHtmlCode(config.title, config.subtitle),
}}
/>
))}
</div>
)
}然后回到浏览器,在应用首页:功能展示-->点击:- Size Modifiers 内置字号调整工具,或者直接地址上输入:http://localhost:3000/1-size-modifiers,可以看到5种不同字体尺寸的实际效果。后续,可以搭配tailwindcss的断点前缀和字体修饰符来实现不同分辨率下的字体大小调整。
样式自定义方式
如果上面默认的修饰符的颜色或字体大小需要进行进行调整,我们有以下几种方式:
1. Element modifiers
使用元素修饰符
element modifiers直接在HTML中自定义内容中的各个元素的样式。
在app目录创建2-element-modifiers,在此目录下创建page.tsx,拷贝如下代码,然后在浏览器中访问地址 http://localhost:3000/2-element-modifiers,看看自定义样式的效果。
import Link from "next/link"
export default function Home() {
return (
<div className="flex flex-row space-x-6 items-start justify-center h-screen w-screen p-8">
<div className="prose dark:prose-invert">
<h1>⚙️ 默认样式</h1>
<h2>H2:小节标题</h2>
<h3>H3:子小节标题</h3>
<p>没有使用 typography 样式,使用的是浏览器默认的样式,即:User Agent Stylesheet。</p>
<p>
你可以写一些<span style={{ fontWeight: "bold" }}>加粗</span>、<em>斜体</em>或<code>代码片段</code>的文字。
</p>
<blockquote>这是一个引用区域。</blockquote>
<ul>
<li>无序列表项 A</li>
<li>无序列表项 B</li>
</ul>
<ol>
<li>有序列表 1</li>
<li>有序列表 2</li>
</ol>
<pre>
<code>{`function greet(name) {
return 'Hello, ' + name + '!';
}`}</code>
</pre>
<table>
<thead>
<tr>
<th>项目</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td>HTML</td>
<td>超文本标记语言</td>
</tr>
<tr>
<td>CSS</td>
<td>层叠样式表</td>
</tr>
</tbody>
</table>
<h4>功能展示</h4>
<ul>
<li>
<Link href="/size-modifiers">Size Modifiers 内置字号调整工具</Link>
</li>
<li>
<Link href="/size-modifiers">自定义字号 & 颜色</Link>
</li>
<li>
<Link href="/size-modifiers">不使用 typography 样式</Link>
</li>
<li>
<Link href="/gray-scale">Gray Scale 灰度主题</Link>
</li>
</ul>
</div>
<div className="prose dark:prose-invert prose-h1:text-blue-600 prose-h2:text-base prose-h3:text-pink-400 prose-h3:border prose-h3:border-orange-600 prose-h3:rounded-md prose-h3:p-2 prose-p:italic prose-table:border-collapse prose-table:border prose-table:border-gray-300 prose-th:border prose-th:border-gray-300 prose-th:text-center prose-td:border prose-td:border-gray-300 prose-td:text-center">
<h1>✍️ 使用Element Modifiers 个性化。prose-h1:text-blue-600</h1>
<h2>H2:小节标题,使用 prose-h2:text-base 将 h2 的字号设置为 base</h2>
<h3>H3:子小节标题,使用 prose-h3:text-pink-400 prose-h3:border prose-h3:border-orange-600 prose-h3:rounded-md prose-h3:p-2 个性化</h3>
<p>这是一个段落内容,用来演示 typography 样式。行高、字间距、段距等展示的视觉效果。prose-p:italic</p>
<p>
你可以写一些<span style={{ fontWeight: "bold" }}>加粗</span>、<em>斜体</em>或<code>代码片段</code>的文字。
</p>
<blockquote>这是一个引用区域。</blockquote>
<ul>
<li>无序列表项 A</li>
<li>无序列表项 B</li>
</ul>
<ol>
<li>有序列表 1</li>
<li>有序列表 2</li>
</ol>
<pre>
<code>{`function greet(name) {
return 'Hello, ' + name + '!';
}`}</code>
</pre>
<table>
<thead>
<tr>
<th>项目</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td>HTML</td>
<td>超文本标记语言</td>
</tr>
<tr>
<td>CSS</td>
<td>层叠样式表</td>
</tr>
<tr>
<td>示例样式</td>
<td>
prose-table:border-collapse prose-table:border prose-table:border-gray-300 prose-th:border prose-th:border-gray-300 prose-th:text-center prose-td:border
prose-td:border-gray-300 prose-td:text-center
</td>
</tr>
</tbody>
</table>
<h4>功能展示</h4>
<ul>
<li>
<Link href="/1-size-modifiers">Size Modifiers 内置字号调整工具</Link>
</li>
<li>
<Link href="/2-element-modifiers">Element Modifiers 个性化</Link>
</li>
<li>
<Link href="/3-tailwind-config-js">Tailwind Config JS 个性化</Link>
</li>
<li>
<Link href="/4-gray-scale">Gray Scale 灰度主题</Link>
</li>
<li>
<Link href="/5-override-max-width">覆盖默认最大宽度</Link>
</li>
<li>
<Link href="/6-undo-style">撤销prose样式</Link>
</li>
</ul>
</div>
</div>
)
}如果一切顺利,h1、h2、h3、p、以及table的样式都发生了变化,这是最简单的方式,可以通过 prose-[element]:[tailwindcss utitlity]的方式快速调整成需要的样式。
可以查看tailwindcss utitlity相关文档,来查看其具体的效果;
下表是全部修饰符:
| Modifier | Target |
|---|---|
prose-headings:{utility} | h1, h2, h3, h4, th |
prose-lead:{utility} | [class~="lead"] |
prose-h1:{utility} | h1 |
prose-h2:{utility} | h2 |
prose-h3:{utility} | h3 |
prose-h4:{utility} | h4 |
prose-p:{utility} | p |
prose-a:{utility} | a |
prose-blockquote:{utility} | blockquote |
prose-figure:{utility} | figure |
prose-figcaption:{utility} | figcaption |
prose-strong:{utility} | strong |
prose-em:{utility} | em |
prose-kbd:{utility} | kbd |
prose-code:{utility} | code |
prose-pre:{utility} | pre |
prose-ol:{utility} | ol |
prose-ul:{utility} | ul |
prose-li:{utility} | li |
prose-table:{utility} | table |
prose-thead:{utility} | thead |
prose-tr:{utility} | tr |
prose-th:{utility} | th |
prose-td:{utility} | td |
prose-img:{utility} | img |
prose-video:{utility} | video |
prose-hr:{utility} | hr |
2. 全局修改
Element Modifiers虽然很方便,但是比较适合较少页面的场景,如果应用有很多页面,每个页面都需要调整的话,工作量很大,这种场景,需要“全局修改”,通过配置tailwind.config.js的方式来实现。
我们来实现上面同样的效果,先按照步骤一步一步完成,之后再解释相关内容。
在根目录创建 tailwind.config.js 文件,将如下代码复制进去:
/** @type {import('tailwindcss').Config} */
module.exports = {
theme: {
extend: {
typography: () => ({
DEFAULT: {
css: {
h1: {
color: 'var(--color-blue-600)'
},
h2: {
fontSize: 'var(--font-size-base)'
},
h3: {
color: 'var(--color-pink-400)',
border: '1px solid var(--color-orange-600)',
padding: '8px',
borderRadius: '0.6rem'
},
p: {
fontStyle: 'italic'
},
table: {
borderCollapse: 'collapse',
border: '1px solid var(--color-gray-300)'
},
th: {
border: '1px solid var(--color-gray-300)',
textAlign: 'center'
},
td: {
border: '1px solid var(--color-gray-300)',
textAlign: 'center'
}
},
},
xl: {
css: {
h1: {
color: 'blue'
}
}
},
extend: {
css: {
h1: {
color: 'green'
}
}
}
}),
},
},
}在app目录下创建custom.css,输入如下代码:
@import "tailwindcss";
@plugin "@tailwindcss/typography";
@config "../tailwind.config.js";custom.css在app目录下,而tailwind.config.js在项目根目录,所以路径使用../,意思是相对于该目录的上级目录。@config是tailwindcss的指令,用来加载基于JavaScript的配置;
在app目录下创建 3-tailwind-config-js 目录,在此目录下创建page.tsx,拷贝如下代码:
import Link from "next/link"
import "../custom.css"
export default function TailwindConfigJS() {
return (
<div className="flex flex-row space-x-6 items-start justify-center h-screen w-screen p-8">
<div className="prose dark:prose-invert">
<h1>⚙️ Tailwind Config JS 样式</h1>
<h2>H2:小节标题</h2>
<h3>H3:子小节标题</h3>
<p>没有使用 typography 样式,使用的是浏览器默认的样式,即:User Agent Stylesheet。</p>
<p>
你可以写一些<span style={{ fontWeight: "bold" }}>加粗</span>、<em>斜体</em>或<code>代码片段</code>的文字。
</p>
<blockquote>这是一个引用区域。</blockquote>
<ul>
<li>无序列表项 A</li>
<li>无序列表项 B</li>
</ul>
<ol>
<li>有序列表 1</li>
<li>有序列表 2</li>
</ol>
<pre>
<code>{`function greet(name) {
return 'Hello, ' + name + '!';
}`}</code>
</pre>
<table>
<thead>
<tr>
<th>项目</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td>HTML</td>
<td>超文本标记语言</td>
</tr>
<tr>
<td>CSS</td>
<td>层叠样式表</td>
</tr>
</tbody>
</table>
<h4>功能展示</h4>
<ul>
<li>
<Link href="/1-size-modifiers">Size Modifiers 内置字号调整工具</Link>
</li>
<li>
<Link href="/2-element-modifiers">Element Modifiers 个性化</Link>
</li>
<li>
<Link href="/3-tailwind-config-js">Tailwind Config JS 个性化</Link>
</li>
<li>
<Link href="/4-gray-scale">Gray Scale 灰度主题</Link>
</li>
<li>
<Link href="/5-override-max-width">覆盖默认最大宽度</Link>
</li>
<li>
<Link href="/6-undo-style">撤销prose样式</Link>
</li>
</ul>
</div>
</div>
)
}注意,文件顶部的 import "../custom.css"
然后,在浏览器中输入 http://localhost:3000/3-tailwind-config-js ,也会发生同样的变化。
我们来解释下相关的代码。
tailwind.config.js 是一个JavaScript文件,可以在这个文件中定义或扩展 Tailwind 的默认行为,在Tailwind CSS v3的版本中,该文件必不可少,V4移除了该文件的依赖,但是如果使用typography插件进行自定义扩展时,该文件必不可少。
使用
JavaScript意味着可以实现:动态计算、模块化、条件逻辑、扩展性,在构建过程中,Tailwind CSS会读取该文件,根据配置来生成最终的CSS,所以我们重点关注下配置相关的内容。
DEFAULT使用CSS-in-JS syntax来表示CSS规则。
-
传统
CSS是由选择器、属性和值组成的字符串。而CSS-in-JS语法通常使用JavaScript对象来表示这些CSS规则。 -
属性名通常是驼峰式: 例如,
CSS中的background-color在JavaScript对象中会写成backgroundColor。 -
值通常是字符串: 大多数 CSS 值仍然是字符串,例如
'#fff','1rem'。 -
嵌套规则的表示: 对于嵌套的 CSS 规则(如媒体查询、伪类、伪元素),通常会在对象中使用嵌套的对象或特定的语法来表示。
-
使用
DEFAULT来覆盖默认的样式规则,同时里面使用了Tailwind CSS中的一些变量,如果不熟悉这些,可以不使用这些变量,直接使用传统CSS的值。 -
同样
xl是覆盖了内置的prose-xl的h1颜色; -
如果不想修改内置的颜色,可以使用自定义名称,比如:
extend,在使用时只需要传入prose:extend即可,该名称可以自定义;
custom.css是定义要加载自定义的配置,同时在需要使用的页面引入这个样式,即完成了全局样式的处理。
⚠️ 虽然
globals.css中已经引入了tailwindcss和typography,但是如果在该文件中增加自定义配置,会影响全局效果,为了演示其功能,单独增加该文件,重复引用了tailwindcss和typography,在生产环境中,尽量避免此类做法,Next.js + Tailwind的构建流程是:只要CSS文件被引用,就作为入口构建。所以每个被import的CSS文件,都会单独走Tailwind编译流程。这就使得globals.css和custom.css是两个独立的Tailwind编译入口,可以使用不同的配置(甚至插件、preset),但这样也失去了Tailwind原本统一性、按需生成的优势。同时会造成体积大、重复样式。
按照此方式,可以定义不同的主题,比如蓝色系、红色系等等。
灰度主题与风格说明
同样的,该插件默认提供了5种不同的灰阶主题。
在app目录下,创建4-gray-scale目录,在此目录下创建page.tsx,拷贝如下代码:
export const metadata = {
title: "Tailwind Typography 灰阶主题演示",
description: "对比 prose-gray、slate、zinc、neutral、stone 的视觉差异与设计意图",
}
export default function GrayScalePage() {
const generateHtmlCode = (proseClass: string, title: string = "技术文档标题", subtitle: string = "小节标题") => {
return `<div class="${proseClass} dark:prose-invert">
<h1>H1:${title}</h1>
<h2>H2:${subtitle}</h2>
<h3>H3:子小节标题</h3>
<p>这是一个段落内容,用来演示 \`p\` 的样式。包括行高、字间距、段距等相关的内容。</p>
<p>
你可以写一些<strong>加粗</strong>、<em>斜体</em>或<code>代码片段</code>的文字。
</p>
<blockquote>这是一个引用区域。</blockquote>
<ul>
<li>无序列表项 A</li>
<li>无序列表项 B</li>
</ul>
<ol>
<li>有序列表 1</li>
<li>有序列表 2</li>
</ol>
<pre><code>function greet(name) {
return 'Hello, ' + name + '!';
}</code></pre>
<table>
<thead>
<tr><th>项目</th><th>说明</th></tr>
</thead>
<tbody>
<tr><td>HTML</td><td>超文本标记语言</td></tr>
<tr><td>CSS</td><td>层叠样式表</td></tr>
</tbody>
</table>
</div>`
}
const configurations = [
{ proseClass: "prose-gray", title: "灰色主题 gray", subtitle: "灰色小节" },
{ proseClass: "prose-slate", title: "石板色主题 slate", subtitle: "石板色小节" },
{ proseClass: "prose-zinc", title: "锌色主题 zinc", subtitle: "锌色小节" },
{ proseClass: "prose-neutral", title: "中性色主题 neutral", subtitle: "中性色小节" },
{ proseClass: "prose-stone", title: "石色主题 stone", subtitle: "石色小节" },
]
return (
<div className="p-4 w-screen space-y-4">
{/* 顶部说明文案 */}
<section className="max-w-5xl prose dark:prose-invert">
<h1>Tailwind Typography 灰阶主题对比</h1>
<p>
Tailwind 提供了<code>5</code>种灰度排版主题,其目的在于适配不同设计语言中的灰度风格。
</p>
<table>
<thead>
<tr>
<th>名称</th>
<th>风格倾向</th>
<th>色温倾向</th>
<th>应用感受</th>
</tr>
</thead>
<tbody>
<tr>
<td>gray</td>
<td>默认 / 通用</td>
<td>中性偏暖</td>
<td>最通用、最传统</td>
</tr>
<tr>
<td>slate</td>
<td>冷感 / 科技风</td>
<td>偏冷</td>
<td>稍偏蓝调,适合代码类文档</td>
</tr>
<tr>
<td>zinc</td>
<td>金属感 / 极简风</td>
<td>冷灰</td>
<td>非常中性,适合 UI 组件说明文档</td>
</tr>
<tr>
<td>neutral</td>
<td>纯中性色</td>
<td>极中性</td>
<td>略偏灰黄,视觉最柔和</td>
</tr>
<tr>
<td>stone</td>
<td>自然风 / 柔和感</td>
<td>偏暖</td>
<td>类似纸张、石块,有自然复古感</td>
</tr>
</tbody>
</table>
<h2>为什么看起来好像“都差不多”?</h2>
<p>默认背景色相同、字体较小,会掩盖它们在引用、列表符号、代码块、表格边框等处的细节色彩差异,但在不同主题中会有微妙差异。</p>
</section>
{/* 灰阶主题演示区域 */}
<div className="flex flex-row space-x-2">
{configurations.map((config, index) => (
<div
key={index}
className={`w-1/5 prose dark:prose-invert p-2 rounded-lg border border-gray-300 shadow-sm ${config.proseClass}`}
dangerouslySetInnerHTML={{
__html: generateHtmlCode(config.proseClass, config.title, config.subtitle),
}}
/>
))}
</div>
</div>
)
}然后在浏览器中访问 http://localhost:3000/4-gray-scale,查看其效果,灰度排版主题,其目的在于适配不同设计语言中的灰度风格,但是在视觉效果中不太容易区分。
暗黑模式支持
- 每个默认的主题都包含一个精心设计的暗黑模式的版本,如果你在本地测试的时候,正在在晚上,且系统切换为了暗黑模式,那么你会发现在这种情况下,显示的视觉效果很差,不用担心,我们直接在每个使用
prose的地方增加一个dark:prose-invert即可。但是最好给自定义的调整或者主题也配置一个暗黑模式。 - 如果不希望使用暗黑模式,最简单的方式:
- 在
globals.css中,将如下代码进行修改,将前景色和背景色进行调整即可;
@media (prefers-color-scheme: dark) {
:root {
@media (prefers-color-scheme: dark) {
:root {
/*--background: #0a0a0a;
--foreground: #ededed; */
--background: #ffffff;
--foreground: #171717;
}
}- 同时移除
dark:prose-invert
如何覆盖最大宽度限制
每个尺寸修饰符都内置了max-width,旨在尽可能保持内容的可读性,若希望内容完全填充其所在容器的宽度,只需在内容中添加 max-w-none即可覆盖内置的最大宽度。
在app目录下,创建5-override-max-with目录,在此目录下创建page.tsx,拷贝如下代码:
export default function OverrideMaxWidth() {
return (
<div className="flex flex-col space-y-8 p-8">
<div className="prose dark:prose-invert">
<h1>默认行为</h1>
<p>
覆盖最大宽度: 每个尺寸修饰符都内置了一个
max-width(最大宽度),旨在尽可能保持内容的可读性。然而,这并非总是你想要的效果,有时你可能希望内容完全填充其容器的宽度。在这些情况下,你只需在内容中添加 max-w-none
即可覆盖内置的最大宽度:总结要点: prose 类默认行为:Tailwind CSS 的 prose 类(例如 prose-lg, prose-xl 等)在应用到内容块时,会内置一个max-width 限制。 目的: 这个默认的 max-width
是为了提高文本内容的阅读舒适性,防止文本行过长导致难以阅读。 覆盖需求: 有时,你可能不希望内容受到这个 max-width的限制,而是希望它完全填充其父容器的可用宽度。 解决方案:
若要实现内容完全填充容器,只需在应用了 prose 类的元素上额外添加 max-w-none 这个 Tailwind CSS 工具类。 示例: max-w-none会移除 prose 默认设置的最大宽度约束。
</p>
</div>
<div className="prose dark:prose-invert max-w-none">
<h1>Override Max Width</h1>
<p>
覆盖最大宽度 每个尺寸修饰符都内置了一个
max-width(最大宽度),旨在尽可能保持内容的可读性。然而,这并非总是你想要的效果,有时你可能希望内容完全填充其容器的宽度。在这些情况下,你只需在内容中添加 max-w-none
即可覆盖内置的最大宽度:总结要点: prose 类默认行为:Tailwind CSS 的 prose 类(例如 prose-lg, prose-xl 等)在应用到内容块时,会内置一个max-width 限制。 目的: 这个默认的 max-width
是为了提高文本内容的阅读舒适性,防止文本行过长导致难以阅读。 覆盖需求: 有时,你可能不希望内容受到这个 max-width的限制,而是希望它完全填充其父容器的可用宽度。 解决方案:
若要实现内容完全填充容器,只需在应用了 prose 类的元素上额外添加 max-w-none 这个 Tailwind CSS 工具类。 示例: max-w-none会移除 prose 默认设置的最大宽度约束。
</p>
</div>
</div>
)
}在浏览器中访问http://localhost:3000/5-override-max-width,可以查看实际的效果。
如何撤销 prose 样式
如果某些内容不想应用prose的样式,可以通过在元素上增加not-prose来撤消typography样式。
在app目录下,创建6-undo-style目录,在此目录下创建page.tsx,拷贝如下代码:
export default function UndoStyle() {
return (
<div className="flex flex-row space-x-6 items-start justify-center h-screen w-screen p-8">
<div className="prose dark:prose-invert">
<h1>✅ 使用 Typography</h1>
<h2>H2:小节标题</h2>
<h3>H3:子小节标题</h3>
<p>这是一个段落内容,用来演示 typography 样式。行高、字间距、段距等展示的视觉效果。</p>
<p>
你可以写一些<span style={{ fontWeight: "bold" }}>加粗</span>、<em>斜体</em>或<code>代码片段</code>的文字。
</p>
<blockquote>这是一个引用区域。</blockquote>
<ul>
<li>无序列表项 A</li>
<li>无序列表项 B</li>
</ul>
<ol>
<li>有序列表 1</li>
<li>有序列表 2</li>
</ol>
<pre>
<code>{`function greet(name) {
return 'Hello, ' + name + '!';
}`}</code>
</pre>
<table>
<thead>
<tr>
<th>项目</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td>HTML</td>
<td>超文本标记语言</td>
</tr>
<tr>
<td>CSS</td>
<td>层叠样式表</td>
</tr>
</tbody>
</table>
</div>
<div className="prose dark:prose-invert">
<h1 className="not-prose">❌ 撤销 Typography部分样式</h1>
<h2>H2:not-prose</h2>
<h3>H3:子小节标题</h3>
<p>这是一个段落内容,用来演示 typography 样式。行高、字间距、段距等展示的视觉效果。</p>
<p>
你可以写一些<span style={{ fontWeight: "bold" }}>加粗</span>、<em>斜体</em>或<code>代码片段</code>的文字。
</p>
<blockquote>这是一个引用区域。</blockquote>
<ul className="not-prose">
<li>无序列表项 A</li>
<li>无序列表项 B</li>
<li className="text-red-500">增加 not-prose 类,撤销 typography 样式</li>
</ul>
<ol>
<li>有序列表 1</li>
<li>有序列表 2</li>
</ol>
<pre>
<code>{`function greet(name) {
return 'Hello, ' + name + '!';
}`}</code>
</pre>
<table className="not-prose">
<thead>
<tr>
<th>项目</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td>HTML</td>
<td>超文本标记语言</td>
</tr>
<tr>
<td>CSS</td>
<td>层叠样式表</td>
</tr>
<tr>
<td className="text-red-500">增加 not-prose 类,撤销 typography 样式</td>
<td className="text-red-500">增加 not-prose 类,撤销 typography 样式</td>
</tr>
</tbody>
</table>
</div>
</div>
)
}在浏览器中访问http://localhost:3000/6-undo-style,可以查看实际的效果。
修改默认 prose 类名
若出于任何原因的需求,需要修改默认的prose名称,可以在注册插件的使用className选项来进行处理:
@import "tailwindcss";
@plugin "@tailwindcss/typography" {
className: yourdefinename;
}⚠️ 同时,需要所有使用prose类的地方都要进行替换,包括前缀。
总结
@tailwindcss/typography插件为内容密集型页面提供了极致的排版体验,几乎可以一键美化文章、博客、文档等富文本内容。它不仅提升了可读性和专业感,也帮助开发者节省了大量排版与样式调整时间。- 本篇文章带你从创建项目、基础使用,到进阶技巧(如响应式字号、主题灰度、暗黑模式、自定义样式等),系统性掌握了
Typography插件的使用方式。 - 无论你是内容创作者、独立开发者,还是在搭建自己的博客或文档系统,
Tailwind Typography都值得作为你的首选排版解决方案。
📎 示例项目源码: