React Email 组件完全参考:从 Tailwind 样式到 19 个核心组件的实战指南
【免费下载链接】react-email💌 Build and send emails using React项目地址: https://gitcode.com/GitHub_Trending/re/react-email
导读
本指南以 React Email 官方组件参考(COMPONENTS.md)为骨架,逐一定义并解析全部 19 个可用组件(Body、Button、CodeBlock、CodeInline、Column、Container、Font、Head、Heading、Hr、Html、Img、Link、Markdown、Preview、Row、Section、Tailwind、Text),并深入仓库源码(packages/react-email/src/components)印证其底层实现。阅读完本文,你将掌握:如何使用pixelBasedPreset规避rem单位在邮件客户端中的兼容性陷阱、如何组合 Row/Column 构建多栏布局、如何用 CodeBlock/Font 等专用组件呈现代码与字体,以及每个组件 Props 的真实语义与最佳实践。
首要原则:只导入你真正用到的组件。不要在使用组件的代码中遗漏对应 import,也不要引入未使用的组件,这既是包体积优化,也是模板可维护性的基础(见 components/index.ts,所有组件均从
react-email单一入口导出)。
一、可用组件总览
所有组件统一从react-email导入。下表对应文档中列出的 19 个组件及其定位:
| 组件 | 作用 |
|---|---|
Body | 包裹邮件正文内容的容器 |
Button | 被样式化为按钮的链接,内置 Outlook 内边距兼容处理 |
CodeBlock | 基于 Prism.js 的带主题、带正则高亮的代码块 |
CodeInline | 在所有邮件客户端都表现一致的行内代码元素 |
Column | 纵向分隔内容区域(必须与Row搭配使用) |
Container | 在断点处水平居中内容的布局组件 |
Font | 设置邮件字体(支持 web font) |
Head | 承载style、meta等文档级元素 |
Heading | 标题文本块(h1–h6) |
Hr | 分隔内容区域的分割线 |
Html | 包裹邮件的根 html 组件 |
Img | 在邮件中展示图片 |
Link | 指向网页、邮箱地址等任意 URL 的超链接 |
Markdown | 将 Markdown 转换为合法的 react-email 模板代码 |
Preview | 收件箱中显示的预览文本 |
Row | 横向分隔内容区域 |
Section | 可用行和列进行格式化的区块 |
Tailwind | 以 Tailwind CSS 包裹邮件的样式组件 |
Text | 以空白分隔的文本块 |
二、Tailwind:官方推荐的样式方案
2.1 基础用法
官方推荐用 Tailwind 来样式化 React Email 组件:用<Tailwind>包裹邮件内容,直接使用工具类(utility classes)。
import { Tailwind, pixelBasedPreset, Html, Body, Container, Heading, Text, Button } from 'react-email'; export default function Email() { return ( <Html lang="en"> <Tailwind config={{ presets: [pixelBasedPreset], theme: { extend: { colors: { brand: '#007bff', accent: '#28a745' }, }, }, }} > <Body className="bg-gray-100 font-sans"> <Container className="max-w-xl mx-auto p-5"> <Heading className="text-2xl font-bold text-brand mb-4"> Welcome! </Heading> <Text className="text-base text-gray-700 mb-4"> Your content here. </Text> <Button href="https://example.com" className="bg-brand text-white px-6 py-3 rounded-lg block text-center box-border" > Get Started </Button> </Container> </Body> </Tailwind> </Html> ); }Props:config—— Tailwind 配置对象。
2.2 工作原理(源码级)
从 tailwind.tsx 的实现可以看到完整的处理流水线:
- 工具类自动转为内联样式:
Tailwind遍历 React 元素树(mapReactTree),收集所有className拆分出的类名,通过setupTailwind生成样式表,再用cloneElementWithInlinedStyles将可内联规则逐元素克隆为style属性; - 媒体查询被提取到
<head>的<style>标签:不可内联的规则(如媒体查询)由sanitizeNonInlinableRules清洗后,在遇到<head>元素时注入<style>(见 tailwind.tsx)。若存在需要<head>的类却找不到<head>,组件会直接抛错提示你移动<Head />; - CSS 变量被解析:
getCustomProperties提取自定义属性并在内联时解析; - RGB 颜色语法被规范化:
downlevelForEmailClients将颜色值降级为邮件客户端兼容的形式。
2.3 使用注意事项
- 始终使用
pixelBasedPreset:邮件客户端不支持rem单位。该预设(定义于 tailwind.tsx)将fontSize与spacing全部替换为像素值(例如text-base为16px/24px、p-4为16px),确保字号与间距在客户端渲染一致; - 自定义 config 是可选的:默认配置已足够好用,仅在需要品牌色等定制时再
extend; - 避免响应式类(
sm:、md:、lg:):这些断点类在主流邮件客户端支持有限且不可靠,请勿依赖。
三、结构型组件
3.1 Html:邮件根包裹
始终作为最外层组件使用。源码(html.tsx)中lang默认"en"、dir默认"ltr"。
import { Html, Tailwind, pixelBasedPreset } from 'react-email'; <Html lang="en" dir="ltr"> <Tailwind config={{ presets: [pixelBasedPreset] }}> {/* email content */} </Tailwind> </Html>Props:
lang—— 语言代码(如"en"、"es"、"fr");dir—— 文本方向("ltr"或"rtl")。
3.2 Head:文档级元素容器
存放style、meta、title等与文档相关的头部元素。注意要放在<Tailwind>内部——因为 Tailwind 需要在此注入媒体查询样式(若缺<head>会抛错)。
import { Head } from 'react-email'; <Head> <title>Email Title</title> </Head>3.3 Body:正文包裹
import { Body } from 'react-email'; <Body className="bg-gray-100 font-sans"> {/* email content */} </Body>3.4 Container:水平居中容器
最大宽度约束为37.5em(约 600px),源码在 container.tsx 中体现为style={{ maxWidth: '37.5em', ...tableStyle }},同时自动设置align="center"、width="100%"。实现上还做了一个巧妙的兼容处理:把 padding 相关样式拆到内部<td>上,以改善 Klaviyo 与 Outlook 的兼容性(container.tsx)。
import { Container } from 'react-email'; <Container className="max-w-xl mx-auto p-5"> {/* centered content */} </Container>3.5 Section:可组合行列的区块
import { Section } from 'react-email'; <Section className="p-5 bg-white"> {/* section content */} </Section>无障碍说明:<Section>、<Row>、<Container>及<Markdown>生成的表格默认渲染为<table role="presentation">,这样屏幕阅读器不会把它们当作数据表格播报。如果你直接手写裸<table>做布局,请自行加上role="presentation"。
3.6 Row & Column:横纵布局组合
Row横向排布内容区域,Column纵向分隔;Column必须配合Row使用。
import { Section, Row, Column } from 'react-email'; <Section> <Row> <Column className="w-1/2 p-2 align-top"> Left column content </Column> <Column className="w-1/2 p-2 align-top"> Right column content </Column> </Row> </Section>Column 宽度要点:
- 使用百分比宽度(如
w-1/2、w-1/3); - 或使用 Tailwind 宽度工具类;
- 各列宽度之和应等于 100% 或容器宽度。
四、内容型组件
4.1 Preview:收件箱预览文本
显示在收件人收件箱中的预览文字。
import { Preview } from 'react-email'; <Preview>Welcome to our platform - Get started today!</Preview>最佳实践:
- 控制在 140 字符以内;
- 内容要吸引人、有行动导向;
- 始终作为
<Body>内的第一个元素。
4.2 Heading:标题文本(h1–h6)
import { Heading } from 'react-email'; <Heading as="h1" className="text-2xl font-bold text-gray-800 mb-4"> Welcome to Acme </Heading> <Heading as="h2" className="text-xl font-semibold text-gray-600 mb-3"> Getting Started </Heading>Props:as—— HTML 标题级别("h1"至"h6")。
4.3 Text:文本块
import { Text } from 'react-email'; <Text className="text-base leading-6 text-gray-800 my-4"> Your paragraph content here. </Text>4.4 Button:按钮化链接(含 Outlook 兼容)
按钮本质上是一个带样式的<a>链接,源码在 button.tsx 中实现了针对 Outlook 的复杂兼容:
- 通过
msoPaddingAlt: '0px'让 Word 渲染引擎忽略 CSS padding 造成的高度问题; - 用
mso-text-raise(pxToPt计算)微调文本垂直位置; - 用
mso-font-width配合零宽字符 模拟左右内边距——因为 Outlook 的mso-font-width不允许超过 500%,实现会通过computeFontWidthAndSpaceCount自动计算需要重复的空白字符数量(button.tsx)。
import { Button } from 'react-email'; <Button href="https://example.com/verify" target="_blank" className="bg-blue-600 text-white px-5 py-3 rounded block text-center no-underline font-medium box-border" > Verify Email Address </Button>Props:
href(必填)—— 链接目标 URL;target—— 默认"_blank"。
样式技巧:
- 用
block实现通栏按钮; - 用
text-center居中按钮文本; - 加
no-underline去除下划线。
4.5 Link:超链接
import { Link } from 'react-email'; <Link href="https://example.com" target="_blank" className="text-blue-600 underline"> Visit our website </Link>Props:
href(必填);target—— 默认"_blank"。
4.6 Img:图片
import { Img } from 'react-email'; <Img src="https://example.com/logo.png" alt="Company Logo" width="150" height="50" className="block mx-auto" />Props:
src(必填)—— 图片 URL(必须是绝对地址);alt—— 无障碍替代文本(默认"";对有意义的图片应填写描述性内容);width—— 像素宽度;height—— 像素高度。
最佳实践:
- 始终使用托管在 CDN 上的绝对 URL;
- 有意义的图片:编写能覆盖用途和关键细节的描述性
alt(例如alt="Red bicycle leaning against a brick wall",而不是alt="image"); - 装饰性图片(分隔线、背景花纹等):显式传
alt=""让屏幕阅读器干净地跳过,绝不要省略该属性; - 链接中的图片永远不是装饰性的:当
<Img>位于<Link>或<Button>内时,alt必须描述链接去向(如alt="View order #123")。空alt=""会让链接失去可访问名称; - 指定宽高以防止布局抖动;
- 使用
block类避免间距问题。
4.7 Hr:分割线
import { Hr } from 'react-email'; <Hr className="border-solid border-gray-200 my-5" />五、专用组件
5.1 CodeBlock:Prism 高亮代码块
基于 Prism.js 实现,支持主题与正则高亮。组件在渲染时对代码按行切分、逐行用Prism.tokenize分词,再按 token 类型(含 alias)匹配主题样式(code-block.tsx)。
import { CodeBlock, dracula } from 'react-email'; const Email = () => { const code = `export default async (req, res) => { try { const html = await render( <EmailTemplate firstName="John" /> ); return NextResponse.json({ html }); } catch (error) { return NextResponse.json({ error }); } }`; return ( <div className="overflow-auto"> <CodeBlock fontFamily="monospace" theme={dracula} language="javascript" code={code} /> </div> ); };Props:
code(必填)—— 要渲染的代码,纯字符串并包含正确的缩进;language(必填)—— 必须是PrismLanguage中定义的语言(如"javascript"、"python"、"typescript")。完整的语言清单见 languages-available.ts,涵盖 300+ 种语言/别名;若语言未注册,组件会抛出CodeBlock: There is no language defined on Prism called ...错误(code-block.tsx);theme(必填)—— 代码块主题,从react-email导入(dracula、github、nord等)。仓库内置主题定义见 themes.ts,包括xonokai、vscDarkPlus、duotoneForest、holiTheme、cb、vs、materialDark、dracula、shadesOfPurple等,每个主题都包含base样式与各 Prism token 类型的配色;fontFamily(可选)—— 代码块字体族(如"monospace"),主要用于覆盖<Font>设置的全局字体;lineNumbers(可选)—— 是否自动生成行号(布尔值,默认false)。
重要提醒:
- 除非明确要求,否则默认不要使用
lineNumbers; - 始终用带
overflow-auto类的div包裹CodeBlock,避免内边距溢出。
5.2 CodeInline:行内代码
在所有邮件客户端表现一致的行内代码元素。
import { Text, CodeInline } from 'react-email'; <Text className="text-base text-gray-800"> Run <CodeInline className="bg-gray-100 px-1 rounded">npm install</CodeInline> to get started. </Text>5.3 Markdown:Markdown 转邮件模板
将 Markdown 字符串转换为合法的 react-email 模板代码。支持两种传参方式:子元素children,或直接传childrenprop。
import { Html, Markdown } from 'react-email'; const Email = () => { return ( <Html lang="en" dir="ltr"> <Markdown markdownCustomStyles={{ h1: { color: "red" }, h2: { color: "blue" }, codeInline: { background: "grey" }, }} markdownContainerStyles={{ padding: "12px", border: "solid 1px black", }} >{`# Hello, World!`}</Markdown> {/* OR */} <Markdown children={`# This is a ~~strikethrough~~`} /> </Html> ); };Props:
children(必填)—— Markdown 字符串;markdownCustomStyles—— 针对 HTML 元素(h1、h2、p、a、codeInline等)的样式覆盖;markdownContainerStyles—— 容器 div 的样式。
5.4 Font:邮件字体(支持 Web Font)
生成@font-face与全局字体声明的组件,必须放在<head>内。源码(font.tsx)会同时生成mso-font-alt供 Outlook 识别替代字体,默认fontStyle: 'normal'、fontWeight: 400。
import { Head, Font } from 'react-email'; <Head> <Font fontFamily="Roboto" fallbackFontFamily="Arial, sans-serif" webFont={{ url: "https://fonts.gstatic.com/s/roboto/v27/KFOmCnqEu92Fr1Mu4mxKKTU1Kg.woff2", format: "woff2" }} /> </Head>Props:
fontFamily(必填)—— 字体族名称(注意:不要在这里放多个字体,多字体请用fallbackFontFamily);fallbackFontFamily—— 回退字体,支持字符串或数组,数组顺序即优先级(合法值见 font.tsx 中的FallbackFont类型,如Arial、Helvetica、Verdana、Georgia等);webFont—— 包含url和format的对象;fontStyle—— 默认'normal';fontWeight—— 默认400。
支持的字体格式(FontFormat类型,font.tsx):
woff2(推荐)wofftruetypeopentype- 另有
embedded-opentype、svg
注意:并非所有邮件客户端都支持 web font,使用前请核对目标客户端的
@font-face支持情况。
六、实战组合:一个完整的可复用模板骨架
将上述组件组合起来,即可得到一份结构完整、兼容性良好的邮件模板:
import { Html, Head, Body, Container, Section, Row, Column, Preview, Heading, Text, Button, Link, Img, Hr, Tailwind, pixelBasedPreset, } from 'react-email'; export default function WelcomeEmail() { return ( <Html lang="en" dir="ltr"> <Head> <title>Welcome to Acme</title> </Head> <Tailwind config={{ presets: [pixelBasedPreset] }}> <Body className="bg-gray-100 font-sans"> <Preview>Welcome to Acme - Get started today!</Preview> <Container className="max-w-xl mx-auto p-5"> <Section className="bg-white p-5 rounded-lg"> <Img src="https://cdn.example.com/logo.png" alt="Acme logo" width="150" height="50" className="block mx-auto" /> <Heading as="h1" className="text-2xl font-bold text-gray-800 mb-4 text-center"> Welcome aboard! </Heading> <Row> <Column className="w-1/2 p-2 align-top"> <Text className="text-base text-gray-700"> Feature one highlights. </Text> <Link href="https://example.com/features" className="text-blue-600 underline"> Learn more </Link> </Column> <Column className="w-1/2 p-2 align-top"> <Text className="text-base text-gray-700"> Feature two highlights. </Text> <Link href="https://example.com/pricing" className="text-blue-600 underline"> See pricing </Link> </Column> </Row> <Hr className="border-solid border-gray-200 my-5" /> <Button href="https://example.com/get-started" className="bg-blue-600 text-white px-6 py-3 rounded block text-center no-underline font-medium box-border" > Get Started </Button> </Section> </Container> </Body> </Tailwind> </Html> ); }要点回顾:
Preview紧跟<Body>之后,控制收件箱预览文案;Container负责整体水平居中,Section+Row+Column负责内部多栏布局;Button内置 Outlook 兼容逻辑,无需额外 hack;- 所有图片提供描述性
alt,链接内图片的alt说明链接去向; - 全部样式类均基于
pixelBasedPreset的像素体系,避免rem兼容问题。
七、延伸阅读
- 完整组件参考原文:skills/react-email/references/COMPONENTS.md
- 组件实现源码目录:packages/react-email/src/components(每个子目录对应一个组件的
index.ts与实现文件) - 组件导出入口:packages/react-email/src/components/index.ts
- Tailwind 处理流水线核心实现:tailwind.tsx
- CodeBlock 内置主题:themes.ts;支持语言清单:languages-available.ts
- 仓库内置的大量真实邮件示例(覆盖激活、密码重置、订单确认、订阅更新等场景)可作参考:apps/demo/emails
【免费下载链接】react-email💌 Build and send emails using React项目地址: https://gitcode.com/GitHub_Trending/re/react-email
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考