Styling Guide
Comprehensive styling reference for React Email templates.
Styling Approach
Use the Tailwind component for styling if the project uses Tailwind CSS. Otherwise, use inline styles.
import { Tailwind, pixelBasedPreset } from 'react-email';
<Tailwind
config={{
presets: [pixelBasedPreset],
theme: {
extend: {
colors: {
brand: '#007bff',
},
},
},
}}
>
{/* Email content */}
</Tailwind>pixelBasedPreset
Email clients don't support rem units. Always use pixelBasedPreset in your Tailwind configuration to convert rem-based utilities to pixels:
import { pixelBasedPreset } from 'react-email';
<Tailwind config={{ presets: [pixelBasedPreset] }}>Email Client Limitations
Email clients have significant CSS restrictions. Follow these rules:
Unsupported Features
- SVG/WEBP images - Use PNG or JPEG only
- Flexbox/Grid - Use
Row/Columncomponents or tables - Media queries -
sm:,md:,lg:,xl:prefixes don't work - Theme selectors -
dark:,light:prefixes don't work - rem units - Use
pixelBasedPresetfor pixel conversion
Border Handling
Always specify border style and reset other sides when needed:
// Correct - specify border style
<div className="border-solid border border-gray-300" />
// Correct - single side border with reset
<div className="border-none border-l border-solid border-l-gray-300" />
// Incorrect - missing border style
<div className="border border-gray-300" />Component Structure
Head Placement
Always define <Head /> inside <Tailwind> when using Tailwind CSS:
<Html>
<Tailwind config={{ presets: [pixelBasedPreset] }}>
<Head />
<Body>...</Body>
</Tailwind>
</Html>PreviewProps
Only include props that the component actually uses:
const Email = ({ source }: { source: string }) => {
return (
<div>
<a href={source}>Click here</a>
</div>
);
};
Email.PreviewProps = {
source: "https://example.com",
};Default Layout Structure
Body
<Body className="font-sans py-10 bg-gray-100">Container
White background, centered, left-aligned content:
<Container className="mx-auto bg-white p-6 rounded">Footer
Include physical address, unsubscribe link, current year:
<Section className="text-center text-gray-500 text-sm">
<Text className="m-0">123 Main St, City, State 12345</Text>
<Text className="m-0">© {new Date().getFullYear()} Company Name</Text>
<Link href={unsubscribeUrl}>Unsubscribe</Link>
</Section>Typography
Titles
Bold, larger font, larger margins:
<Heading className="text-2xl font-bold text-gray-900 mb-4">Paragraphs
Regular weight, smaller font, smaller margins:
<Text className="text-base text-gray-700 mb-3">Hierarchy
Use consistent spacing that respects content hierarchy. Larger margins for headings, smaller for body text.
Images
- Only include if user requests
- Content images: use responsive sizing (
w-full,h-auto) - Small icons (24-48px): fixed dimensions are acceptable
- Never distort user-provided images
- Never create SVG images
- Always use absolute URLs
- Set descriptive
alttext on meaningful images; pass an explicitalt=""on decorative images so screen readers skip them — never omit the attribute
{/* Meaningful image — describe purpose and details */}
<Img
src="https://example.com/hero.png"
alt="A team of engineers reviewing code on a laptop"
className="w-full h-auto"
/>
{/* Decorative image — always pass an empty alt string so screen readers skip it */}
<Img
src="https://example.com/divider.png"
alt=""
className="w-full"
/>Buttons
Always use box-border to prevent padding overflow:
<Button
href="https://example.com"
className="bg-blue-600 text-white px-5 py-3 rounded box-border block text-center no-underline"
>
Click Here
</Button>Layout
Mobile-First
Always design for mobile by default:
- Use stacked layouts that work on all screen sizes
- Max-width around 600px for main container
- Remove default spacing/margins/padding between list items
Multi-Column
Use Row and Column components instead of flexbox/grid:
<Row>
<Column className="w-1/2">Left content</Column>
<Column className="w-1/2">Right content</Column>
</Row>Dark Mode
When requested, use dark backgrounds:
- Container: black (
#000) - Background: dark gray (
#151516)
<Body className="bg-[#151516]">
<Container className="bg-black text-white">Colors and Brand Consistency
Gathering Brand Colors
Before creating emails, collect these colors from the user:
- Primary: Main brand color for buttons, links, key accents
- Secondary: Supporting color for borders, backgrounds, less prominent elements
- Text: Main body text color (suggest
#1a1a1afor light backgrounds) - Text muted: Secondary text like captions, footers (suggest
#6b7280) - Background: Email body background (suggest
#f4f4f5) - Surface: Container/card background (typically
#ffffff)
Tailwind Configuration File
Create a centralized Tailwind config file that all email templates import. Using satisfies TailwindConfig provides intellisense support for all configuration options:
// emails/tailwind.config.ts
import { pixelBasedPreset, type TailwindConfig } from 'react-email';
export default {
presets: [pixelBasedPreset],
theme: {
extend: {
colors: {
brand: {
primary: '#007bff',
secondary: '#6c757d',
},
},
},
},
} satisfies TailwindConfig;
// For non-Tailwind brand assets (optional)
export const brandAssets = {
logo: {
src: 'https://example.com/logo.png',
alt: 'Company Name',
width: 120,
},
};Using Tailwind Config
Import the shared config in every email template:
import tailwindConfig, { brandAssets } from './tailwind.config';
<Tailwind config={tailwindConfig}>
<Body className="bg-gray-100 font-sans">
<Container className="bg-white p-6">
<Img src={brandAssets.logo.src} alt={brandAssets.logo.alt} width={brandAssets.logo.width} />
<Button className="bg-brand-primary text-white">Action</Button>
</Container>
</Body>
</Tailwind>Maintaining Consistency
- Always use the brand config - Never hardcode colors in individual templates
- Update config, not templates - When colors change, update
tailwind.config.tsonly - Use semantic names -
bg-brand-primarynotbg-[#007bff] - Ensure contrast - Test that text is readable against backgrounds (WCAG AA: 4.5:1 ratio)
Asset Locations
Direct users to place brand assets in appropriate locations:
- Logo and images: Host on a CDN or public URL. For local development, place in
emails/static/. - Custom fonts: Use the
Fontcomponent with a web font URL (Google Fonts, Adobe Fonts, or self-hosted).
Example prompt for gathering brand info:
"Before I create your email template, I need some brand information to ensure consistency. Could you provide:
- Your primary brand color (hex code, e.g., #007bff)
- Your logo URL (must be a publicly accessible PNG or JPEG)
- Any secondary colors you'd like to use
- Style preference (modern/minimal or classic/traditional)"
Best Practices
- Make templates unique - Not generic, tailored to user's request
- Test across clients - Gmail, Outlook, Apple Mail, Yahoo Mail
- Keep file size under 102KB - Gmail clips larger emails
- Use keywords strategically - Increase engagement in email body
- Inline styles as fallback - Some clients strip
<style>tags