---
name: template-design
description: Build HTML email templates that render everywhere. Use when designing email layouts, fixing Outlook rendering, implementing dark mode, adding accessibility, or choosing a templating framework.
license: MIT
---
# Template Design
Build HTML email templates that render correctly across every major email client.
## When to use this skill
- Building an HTML email template from scratch
- Debugging rendering issues in Outlook, Gmail, or other clients
- Making an existing template responsive for mobile
- Adding dark mode support to email templates
- Improving email accessibility for screen readers
- Choosing between email frameworks (MJML, React Email, Maizzle)
- Optimizing image-to-text ratio for deliverability
- Template linting is failing or flagging issues
## Related skills
- `email-copywriting` - writing email content that people actually read
- `spam-filter-avoidance` - content patterns that trigger spam filters
- `email-compliance` - legal requirements including unsubscribe links
- `ab-testing` - testing different template variants
---
## The fundamental problem
Email HTML is not web HTML. There are no standards for how email clients render HTML and CSS. Every client does it differently, and the worst offender - Outlook on Windows - uses Microsoft Word's rendering engine, not a browser engine. This means you're building for a fragmented landscape where the rules of web development don't apply.
The core principle: **code for the worst client, enhance for the best.**
## Document structure
Start every email template with this skeleton:
```html
Email Subject Here
```
Key points:
- The VML and Office namespaces (`xmlns:v`, `xmlns:o`) are required for Outlook to handle vector graphics and layout settings properly.
- `` tells clients that support it (Apple Mail, Outlook on Mac) that your email has both light and dark mode styles.
- The `
```
### Two-column layout with mobile stacking
```html
```
This is the "hybrid" or "ghost table" technique. The outer `div` elements with `display: inline-block` stack naturally on small screens, while the MSO conditional comments provide a fixed-width table layout specifically for Outlook.
### Layout rules
- **Max width: 600px.** This is the de facto standard. Some modern clients support wider, but 600px guarantees no horizontal scrolling.
- **Use `role="presentation"` on every layout table.** This tells screen readers the table is for layout, not data. Critical for accessibility.
- **Never use `
` for actual data display without removing `role="presentation"`.** If you're showing tabular data (pricing, order items), use semantic table markup without the role attribute.
- **Avoid rowspan.** It breaks in Outlook. Use nested tables instead.
- **Set both `width` attribute and `max-width` style.** The attribute is for Outlook (which ignores CSS width on tables), the style is for everything else.
## CSS support: what works and what doesn't
### Universally safe CSS properties
These work in all major clients (Gmail, Outlook, Apple Mail, Yahoo):
| Property | Notes |
|----------|-------|
| `color` | Use hex values, not `rgb()` or `hsl()` |
| `background-color` | Same - hex only for maximum compatibility |
| `font-family` | System fonts only for reliable rendering |
| `font-size` | Use `px`, not `em` or `rem` |
| `font-weight` | `bold` or numeric values |
| `font-style` | `normal`, `italic` |
| `text-align` | `left`, `center`, `right` |
| `text-decoration` | `none`, `underline` |
| `line-height` | Use unitless values or `px` |
| `padding` | Works on `td` elements; write out each side separately |
| `border` | Works on `td` and `table` |
| `width`, `height` | On `td`, `table`, `img` |
| `vertical-align` | On `td` |
### Properties that break in Outlook
| Property | Status in Outlook | Workaround |
|----------|-------------------|------------|
| `display: flex` | Ignored | Use tables |
| `display: grid` | Ignored | Use tables |
| `float` | Partially works, unreliable | Use tables |
| `margin` | Partially works on block elements, ignored on `td` | Use `padding` on `td` cells |
| `border-radius` | Ignored | Use VML for rounded corners, or accept square corners in Outlook |
| `background-image` | Ignored on `td`/`div` | Use VML backgrounds (see below) |
| `max-width` | Ignored on `table` | Set both `width` attribute and `max-width` style |
| `gap` | Not supported | Use padding/margin on child elements |
| CSS shorthand (`padding: 10px 20px`) | Partially works | Write each side separately: `padding-top`, `padding-right`, etc. |
### Properties that Gmail strips
Gmail strips `
```
### Mobile design rules
- **Minimum touch target: 44x44px.** Apple's Human Interface Guidelines and WCAG both specify this. Buttons smaller than this are hard to tap.
- **Body text: 16px minimum.** Anything smaller is hard to read on mobile without zooming.
- **Single column for mobile.** Multi-column layouts should stack vertically on screens under 600px.
- **Full-width buttons on mobile.** Don't make users tap a tiny centered button.
## Dark mode
More than 80% of users have dark mode enabled on at least one device. Your emails need to handle it.
### How clients apply dark mode
There are three categories:
1. **No changes** - Client renders your email as-is (rare).
2. **Partial inversion** - Client changes background colors but leaves other elements alone (Gmail on Android).
3. **Full inversion** - Client inverts colors, adjusts images, and re-renders the email (Apple Mail, Outlook on Mac).
### Declaring dark mode support
Add these meta tags in ``:
```html
```
And this CSS:
```html
```
### Writing dark mode overrides
```html
```
### Dark mode design rules
- **Avoid pure white (#FFFFFF) and pure black (#000000).** Apple Mail auto-inverts these. Use `#FDFDFD` and `#1a1a1a` instead.
- **Use transparent PNGs for logos** so they sit cleanly on any background color.
- **Add a subtle border or padding around logos** so they don't disappear against dark backgrounds.
- **Test button colors.** A dark blue button on a dark background becomes invisible. Choose colors with enough contrast in both modes.
- **Don't embed text in images.** The text can't be re-colored in dark mode, and will look wrong against the inverted background.
### Dark mode client support
| Client | `prefers-color-scheme` | `[data-ogsc]` | Auto-inversion |
|--------|----------------------|---------------|----------------|
| Apple Mail | Yes | No | Yes (can override) |
| iOS Mail | Yes | No | Yes (can override) |
| Outlook (Mac) | Yes | No | Yes |
| Outlook.com | No | Yes | Partial |
| Outlook (Windows) | No | No | No |
| Gmail (web) | No | No | No |
| Gmail (Android) | No | No | Partial |
| Gmail (iOS) | No | No | Partial |
| Yahoo Mail | No | No | Partial |
## Typography
### System font stacks
Web fonts have limited email support - they work in Apple Mail, iOS Mail, and Outlook on Mac, but not in Gmail, Outlook on Windows, or Yahoo. Always specify a full fallback stack.
```css
/* Sans-serif (recommended for most emails) */
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
/* Serif (for editorial / newsletter style) */
font-family: Georgia, 'Times New Roman', Times, serif;
/* Monospace (for code, order numbers) */
font-family: 'Courier New', Courier, monospace;
```
### Using web fonts (progressive enhancement)
If you want to try web fonts, use `@import` or `` in `` with a full fallback stack. Clients that don't support web fonts will use the fallback.
```html
```
**Note:** Gmail strips `@import` entirely. Only use web fonts if you accept that most Gmail users will see the fallback.
### Typography sizing
| Element | Desktop | Mobile |
|---------|---------|--------|
| Body text | 16px | 16px (minimum) |
| Headings (H1) | 28-32px | 24-28px |
| Headings (H2) | 22-24px | 20-22px |
| Preheader/small text | 12-14px | 14px |
| Button text | 16-18px | 16-18px |
- **Line height:** 1.5 for body text, 1.2-1.3 for headings.
- **Paragraph spacing:** Use `padding-bottom` on `
` elements or `margin-bottom` on `
` tags (test margin behavior across clients).
## Images
### General rules
- **Host images externally.** Don't use base64-encoded images in email HTML - many clients block them, and they bloat file size.
- **Always include `alt` text.** Many clients block images by default. Alt text ensures recipients understand the email even without images.
- **Set explicit `width` and `height` attributes.** This prevents layout shifting when images load.
- **Use `display: block`** on images to prevent the gap that appears below images in some clients.
```html
```
### Retina/HiDPI images
For sharp images on retina displays, export images at 2x the display size and constrain with `width` and `height` attributes:
```html
```
### Image formats
| Format | Use for | Email support |
|--------|---------|---------------|
| JPEG | Photos, complex images | Universal |
| PNG | Logos, graphics with transparency | Universal |
| GIF | Simple animations, icons | Universal (animated GIFs play in most clients except Outlook on Windows, which shows the first frame) |
| SVG | - | Poor support - avoid in email |
| WebP | - | Partial support - avoid for now |
### Background images
Outlook ignores CSS `background-image`. Use VML (Vector Markup Language) for Outlook with a CSS fallback for everything else:
```html
Content over the background image
```
### Image-to-text ratio and deliverability
Spam filters can't read text inside images. Image-heavy emails look suspicious because spammers historically used image-only emails to bypass keyword-based filters.
**Rules of thumb:**
- Include at least 500 characters of real text (not in images). Research shows that emails with 500+ characters of text pass spam filters regardless of image count.
- Aim for roughly 60% text to 40% images by visual area.
- Never send an image-only email. Even a single-image newsletter needs real text above and below.
- Always add descriptive `alt` text to images - it counts as readable text for some spam filters and helps recipients with images disabled.
## Buttons
Bulletproof buttons work everywhere, including Outlook. The standard approach uses a table with padding:
```html
```
For Outlook, which ignores `border-radius` and sometimes clips padding on links, add VML:
```html
Get Started
```
## Accessibility
Email accessibility matters - roughly 15% of the global population has some form of disability. The European Accessibility Act (EAA), effective in 2025, expands legal requirements for digital accessibility.
### Essential practices
1. **Use semantic heading structure.** Put an `
` in your email for the main topic. Screen reader users navigate by headings - 72% of emails tested lack proper heading structure.
2. **Add `role="presentation"` to layout tables.** Without it, screen readers announce "table with X rows and Y columns" for every layout table.
3. **Write meaningful alt text.** Not "image1.jpg" - describe what the image shows and why it matters. For decorative images, use `alt=""` (empty, not missing).
4. **Use sufficient color contrast.** WCAG requires 4.5:1 contrast ratio for body text and 3:1 for large text (18px+ or 14px+ bold). 51% of emails fail this.
5. **Don't rely on color alone.** Links should be underlined, not just colored differently. Error states should include text, not just red.
6. **Set the `lang` attribute** on the `` tag so screen readers use the correct pronunciation.
7. **Use real text, not images of text.** Screen readers can't read text in images. It also breaks in dark mode, can't be resized, and is invisible when images are blocked.
8. **Logical reading order.** Screen readers follow the HTML source order, not the visual layout. Make sure your HTML reads in a sensible order when stripped of all styling.
### Accessible links
```html
View your monthly report
Click here
```
## Template linting and validation
Production email platforms lint templates before sending. Common automated checks include:
- **Spam phrase detection.** Phrases like "act now", "buy now", "click here", "free money", "guaranteed", "no obligation", "congratulations" raise spam filter scores. These are flagged as warnings.
- **Variable validation.** Used-but-undeclared variables (`{{company}}` in the template but not defined) are errors. Declared-but-unused variables are warnings.
- **Insecure URLs.** Any `href="http://..."` (not HTTPS) is an error. Mixed content triggers security warnings and damages trust.
- **Missing unsubscribe link.** Marketing emails without an unsubscribe link violate CAN-SPAM, GDPR, and the Google/Yahoo 2024 bulk sender requirements. Transactional emails are exempt.
Platforms like [molted.email](https://molted.email) enforce these rules automatically during template creation and block sends when critical lint rules fail.
### HTML sanitization
Email HTML goes through sanitization before sending to strip potentially dangerous content:
- **Allowed tags:** `p`, `br`, `a`, `b`, `i`, `em`, `strong`, `u`, `ul`, `ol`, `li`, `h1`-`h6`, `table`, `thead`, `tbody`, `tr`, `td`, `th`, `img`, `div`, `span`, `blockquote`, `pre`, `code`
- **Stripped automatically:** `