React Email Guide: Build JSX Emails That Hold Up in Outlook
Build with React Email's table-backed components such as Row, Column and Button rather than flexbox, then check the rendered HTML in real clients, because the dev preview runs in a browser, not in Outlook or Gmail.
No signup · Five clients free, Outlook Classic included · All 21 with an account
The checker needs a computer screen.
A free account opens all 21 clients and keeps your checks for 7 days. Create a free account →
Philippe Kam, founder of Emailens · Published 4 Mar 2026 · Updated 28 Oct 2026
@emailens/engine 0.18.22 · data last changed 10 Nov 2026
Part of the HTML email guide · all guides
React Email lets you write emails with React components instead of hand-writing HTML tables. This guide covers setup, the components and the HTML they compile to, styling that survives email clients, rendering to an HTML string, and testing the result in real inboxes.
What React Email does
HTML email development still means <table> layouts, inline styles on every element, and testing across a dozen clients that each interpret CSS differently. React Email replaces this with a component-based workflow: you write JSX, and it compiles to the table-based HTML that email clients expect.
Components like Row and Column compile to tables automatically, so you get flexbox-like ergonomics without the compatibility issues that come with actual flexbox. If you prefer markup over JSX, the MJML guide covers the main alternative.
Install React Email and run the preview server
npm install @react-email/components react-email
# or with bun
bun add @react-email/components react-emailReact Email provides a dev server (email dev) for local preview. For production, the render() function compiles JSX to an HTML string (see below).
React Email components and the HTML they compile to
React Email ships a small set of components that each compile to email-safe HTML. Here's what each one does:
HtmlRoot wrapper. Sets DOCTYPE and xmlns.
HeadContains <meta> tags, <title>, and embedded styles.
BodyWraps all visible content. Accepts style prop for background color.
ContainerCenters content with a max-width. Compiles to a centered <table>.
Row / ColumnTable-based grid. Use instead of flexbox or CSS grid.
SectionGroups content blocks. Renders as a <table> row.
TextParagraph element with email-safe defaults.
ImgImage with required width/height for Outlook. Always include alt text.
LinkAnchor tag with target="_blank" default.
ButtonCall-to-action button using a padded <a> tag for maximum client support.
HrHorizontal rule using a <table> border trick for consistency.
A complete React Email template
Here's a welcome email using the core components. Note the inline styles: React Email supports style objects, not CSS classes.
import {
Html, Head, Body, Container,
Row, Column, Text, Img, Button, Hr
} from '@react-email/components';
export default function WelcomeEmail({ name }: { name: string }) {
return (
<Html>
<Head />
<Body style={{ backgroundColor: '#f6f6f6', fontFamily: 'Arial, sans-serif' }}>
<Container style={{ maxWidth: '600px', margin: '0 auto', padding: '20px' }}>
<Img
src="https://example.com/logo.png"
width="120"
height="36"
alt="Company Logo"
/>
<Text style={{ fontSize: '24px', fontWeight: 'bold', marginTop: '24px' }}>
Welcome, {name}!
</Text>
<Text style={{ color: '#666', lineHeight: '1.6' }}>
We're glad you're here. Here's what you can do next:
</Text>
<Button
href="https://example.com/dashboard"
style={{
backgroundColor: '#000',
color: '#fff',
padding: '12px 24px',
borderRadius: '6px',
textDecoration: 'none',
}}
>
Go to Dashboard
</Button>
<Hr style={{ borderColor: '#eee', margin: '24px 0' }} />
<Text style={{ fontSize: '12px', color: '#999' }}>
You received this because you signed up at example.com
</Text>
</Container>
</Body>
</Html>
);
}Styling React Email for Gmail and Outlook
Email clients have inconsistent CSS support. Follow these rules to avoid surprises:
- Always use inline styles: Gmail keeps a
<style>block only in the head and within a size limit, and its apps drop it for accounts that are not Google accounts - No flexbox or grid: Outlook ignores both. Use
Row/Columninstead - Set explicit width/height on images: prevents layout shifts in Outlook
- Use web-safe font stacks: custom fonts via @font-face are unsupported in many clients
- Give the colour its own property: Outlook Classic drops a whole
backgroundshorthand it cannot parse, colour included, so setbackground-coloron its own (Outlook fallbacks)
Using Tailwind through React Email's <Tailwind> component? Version 4 breaks breakpoints in Gmail; see fixing Tailwind v4 media queries in Gmail. For multi-column layouts that must hold in Outlook, see Outlook ghost tables.
Props, conditions and loops
Because React Email is just React, you get conditional rendering and loops for free. This is one of its biggest advantages over raw HTML templates:
// Conditional content based on props
export default function NotificationEmail({
type,
items,
}: {
type: 'welcome' | 'invoice';
items?: { name: string; price: string }[];
}) {
return (
<Html>
<Body>
<Container>
{type === 'welcome' && (
<Text>Welcome to our platform!</Text>
)}
{type === 'invoice' && items && (
<>
<Text>Here's your invoice:</Text>
{items.map((item, i) => (
<Row key={i}>
<Column>{item.name}</Column>
<Column style={{ textAlign: 'right' }}>{item.price}</Column>
</Row>
))}
</>
)}
</Container>
</Body>
</Html>
);
}Render React Email to HTML with render()
To send a template, call render() from @react-email/render on the component and hand the HTML string it returns to your email provider. The pretty option indents the output so you can read it. renderAsync() was the v2 API and is deprecated in React Email v3 and later.
Test React Email templates in real email clients
The React Email dev server only shows how your email looks in a browser. It won't catch the CSS properties that Outlook silently drops, the styles Gmail strips, or the dark mode transforms Apple Mail applies.
Emailens can take your React Email JSX source directly. It compiles, transforms per-client, and flags every compatibility issue with fix snippets in React Email syntax. For the full pre-send routine, see how to test HTML emails.
Spacing gaps in Outlook or words running together after render? The React Email and jsx-email troubleshooting guide covers withMargin, renderWhitespace and pxToPt with exact fixes.
Questions
Why use React Email instead of traditional HTML email templates?
React Email allows you to build templates using reusable component architecture, TypeScript type safety, props, and conditional logic. It then compiles clean, table-based HTML compatible with legacy clients like Outlook and Gmail.
Does React Email automatically inline CSS styles?
Yes. When you use the @react-email/render utility with inline styling or @react-email/tailwind, it inlines critical CSS directly onto HTML elements to ensure mobile email clients don't lose formatting.
How do I turn a React Email template into an HTML string?
Call render() from @react-email/render with your component, for example await render(<WelcomeEmail name="Ada" />), and send the HTML string it returns through your email provider. renderAsync() was the v2 API and is deprecated in React Email v3 and later.
How do I preview and test React Email templates locally?
You can run 'email dev' to view templates in the local React Email browser previewer. However, to test true rendering across 21+ real client engines (Gmail sanitizer, Outlook Word engine), you should test the rendered HTML in Emailens.
Your next question
Also useful: HTML email checker · Test React Email templates · Check Resend emails in 21 clients
Paste the email that broke.
No signup · Five clients free, Outlook Classic included · All 21 with an account
The checker needs a computer screen.
Get new email CSS fixes by email, or follow by RSS.