HTML Email Best Practices
Master the art of creating HTML emails that work everywhere.
HTML emails are notoriously tricky. What works perfectly in Gmail might break in Outlook. What looks great on mobile might be unreadable on desktop. Email clients have wildly different rendering engines, limited CSS support, and unpredictable behavior. In this guide, you’ll learn battle-tested techniques for creating HTML emails that work reliably across all major email clients and devices.
Building HTML emails requires a different mindset than building websites—think tables, inline styles, and defensive coding.
The Email HTML Landscape
Email clients use different rendering engines:
- Gmail - Custom engine with limited CSS
- Outlook (Windows) - Microsoft Word rendering engine
- Apple Mail - WebKit (Safari engine)
- Outlook.com - Modern web standards
- Yahoo Mail - Custom engine
- Mobile clients - Various (iOS Mail, Gmail app, etc.)
This fragmentation means you can’t use modern CSS features you’d use on websites.
Basic Email HTML Structure
Start with this foundation:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Email Subject</title>
<style>
/* CSS goes here */
</style>
</head>
<body style="margin: 0; padding: 0; font-family: Arial, sans-serif;">
<table role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%">
<tr>
<td style="padding: 20px 0;">
<!-- Email content goes here -->
</td>
</tr>
</table>
</body>
</html>Use Tables for Layout
Yes, really. Tables are the most reliable way to create email layouts:
<table role="presentation" cellspacing="0" cellpadding="0" border="0" width="600" style="margin: 0 auto;">
<!-- Header -->
<tr>
<td style="background: #0066cc; padding: 20px; text-align: center;">
<h1 style="color: white; margin: 0;">Company Name</h1>
</td>
</tr>
<!-- Content -->
<tr>
<td style="padding: 40px 30px; background: #ffffff;">
<h2 style="margin: 0 0 20px 0;">Email Heading</h2>
<p style="margin: 0 0 15px 0; line-height: 1.5;">
Email content goes here...
</p>
</td>
</tr>
<!-- Footer -->
<tr>
<td style="background: #f4f4f4; padding: 20px; text-align: center; font-size: 12px; color: #666;">
© 2024 Company Name. All rights reserved.
</td>
</tr>
</table>Important attributes:
role="presentation"- Tells screen readers this is layout, not datacellspacing="0"- Removes space between cellscellpadding="0"- Removes padding in cellsborder="0"- Removes table borders
Inline CSS is Essential
Most email clients strip <style> tags. Use inline styles:
<!-- ❌ Bad: External styles won't work -->
<p class="text">Hello</p>
<!-- ✅ Good: Inline styles -->
<p style="color: #333; font-size: 16px; line-height: 1.5; margin: 0 0 15px 0;">
Hello
</p>You can use <style> tags for media queries, but always include inline styles as fallback.
Responsive Email Design
Use media queries for mobile optimization:
<style>
/* Desktop styles (inline styles are mobile-first) */
@media only screen and (min-width: 600px) {
.container {
width: 600px !important;
}
.column {
width: 50% !important;
}
}
</style>
<table role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%" class="container">
<tr>
<td class="column" style="display: inline-block; width: 100%; vertical-align: top;">
Column 1
</td>
<td class="column" style="display: inline-block; width: 100%; vertical-align: top;">
Column 2
</td>
</tr>
</table>Images in Email
Always Include Alt Text
<img
src="https://example.com/logo.png"
alt="Company Logo"
width="200"
height="50"
style="display: block; border: 0;"
>Key Image Attributes
widthandheight- Prevent layout shiftsalt- Shows when images are blockedstyle="display: block;"- Removes gap below imageborder="0"- Removes border in Outlook
Host Images Externally
<!-- ✅ Good: Full URL -->
<img src="https://cdn.example.com/email-header.jpg" alt="Header">
<!-- ❌ Bad: Relative path -->
<img src="/images/header.jpg" alt="Header">
<!-- ❌ Bad: Embedded (increases email size) -->
<img src="data:image/png;base64,..." alt="Header">Buttons That Work
Table-based Button
The most reliable button approach:
<table role="presentation" cellspacing="0" cellpadding="0" border="0">
<tr>
<td style="border-radius: 4px; background: #0066cc;">
<a
href="https://example.com/action"
style="display: inline-block; padding: 12px 24px; font-family: Arial, sans-serif; font-size: 16px; color: #ffffff; text-decoration: none; border-radius: 4px;">
Click Here
</a>
</td>
</tr>
</table>Bulletproof Button (VML for Outlook)
<!--[if mso]>
<v:roundrect xmlns:v="urn:schemas-microsoft-com:vml" xmlns:w="urn:schemas-microsoft-com:office:word" href="https://example.com" style="height:40px;v-text-anchor:middle;width:200px;" arcsize="10%" stroke="f" fillcolor="#0066cc">
<w:anchorlock/>
<center style="color:#ffffff;font-family:Arial,sans-serif;font-size:16px;">
Click Here
</center>
</v:roundrect>
<![endif]-->
<!--[if !mso]><!-->
<table role="presentation" cellspacing="0" cellpadding="0" border="0">
<tr>
<td style="border-radius: 4px; background: #0066cc;">
<a href="https://example.com" style="display: inline-block; padding: 12px 24px; color: #ffffff; text-decoration: none;">
Click Here
</a>
</td>
</tr>
</table>
<!--<![endif]-->Text Formatting
Safe Font Stack
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 1.5; color: #333333;">
Your text here
</p>Safe fonts:
- Arial
- Helvetica
- Georgia
- Times New Roman
- Courier New
- Verdana
Spacing and Margins
<!-- Use padding and margin inline -->
<p style="margin: 0 0 15px 0; padding: 0;">Paragraph</p>
<!-- Add spacing with empty cells -->
<tr>
<td style="height: 20px; font-size: 0; line-height: 0;"> </td>
</tr>Dark Mode Support
Optimize for dark mode:
<style>
@media (prefers-color-scheme: dark) {
.bg-white { background-color: #000000 !important; }
.text-dark { color: #ffffff !important; }
}
</style>
<table role="presentation" width="600" class="bg-white">
<tr>
<td style="padding: 20px;">
<p class="text-dark" style="color: #333333;">
This text adapts to dark mode
</p>
</td>
</tr>
</table>Complete Email Template
Here’s a production-ready template:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Newsletter</title>
<style>
body { margin: 0; padding: 0; }
table { border-collapse: collapse; }
img { border: 0; display: block; }
@media only screen and (max-width: 600px) {
.container { width: 100% !important; }
.mobile-padding { padding: 10px !important; }
}
</style>
</head>
<body style="margin: 0; padding: 0; font-family: Arial, sans-serif; background-color: #f4f4f4;">
<!-- Wrapper -->
<table role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%" style="background-color: #f4f4f4;">
<tr>
<td style="padding: 20px 0;">
<!-- Email Container -->
<table role="presentation" cellspacing="0" cellpadding="0" border="0" width="600" class="container" style="margin: 0 auto; background-color: #ffffff;">
<!-- Header -->
<tr>
<td style="background-color: #0066cc; padding: 30px; text-align: center;">
<img
src="https://example.com/logo.png"
alt="Company Logo"
width="150"
height="40"
style="display: block; margin: 0 auto;"
>
</td>
</tr>
<!-- Hero Image -->
<tr>
<td>
<img
src="https://example.com/hero.jpg"
alt="Hero Image"
width="600"
height="300"
style="width: 100%; height: auto; display: block;"
>
</td>
</tr>
<!-- Content -->
<tr>
<td class="mobile-padding" style="padding: 40px 30px;">
<h1 style="margin: 0 0 20px 0; font-size: 28px; line-height: 1.3; color: #333333;">
Welcome to Our Newsletter
</h1>
<p style="margin: 0 0 15px 0; font-size: 16px; line-height: 1.5; color: #666666;">
Thank you for subscribing! We're excited to share our latest updates with you.
</p>
<p style="margin: 0 0 25px 0; font-size: 16px; line-height: 1.5; color: #666666;">
Here's what you can expect from us...
</p>
<!-- Button -->
<table role="presentation" cellspacing="0" cellpadding="0" border="0">
<tr>
<td style="border-radius: 4px; background-color: #0066cc;">
<a
href="https://example.com/subscribe"
style="display: inline-block; padding: 14px 28px; font-family: Arial, sans-serif; font-size: 16px; color: #ffffff; text-decoration: none; border-radius: 4px; font-weight: bold;">
Get Started
</a>
</td>
</tr>
</table>
</td>
</tr>
<!-- Divider -->
<tr>
<td style="padding: 0 30px;">
<table role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%">
<tr>
<td style="border-top: 1px solid #e0e0e0;"></td>
</tr>
</table>
</td>
</tr>
<!-- Footer -->
<tr>
<td style="padding: 30px; text-align: center; background-color: #f9f9f9;">
<p style="margin: 0 0 10px 0; font-size: 12px; line-height: 1.5; color: #999999;">
© 2024 Company Name. All rights reserved.
</p>
<p style="margin: 0; font-size: 12px; line-height: 1.5; color: #999999;">
123 Street Name, City, State 12345
</p>
<p style="margin: 10px 0 0 0; font-size: 12px; line-height: 1.5;">
<a href="https://example.com/unsubscribe" style="color: #0066cc; text-decoration: underline;">
Unsubscribe
</a>
</p>
</td>
</tr>
</table>
<!-- End Email Container -->
</td>
</tr>
</table>
<!-- End Wrapper -->
</body>
</html>Testing Your Emails
Test Across Clients
- Gmail (web, iOS, Android)
- Outlook (Windows, Mac, web)
- Apple Mail (Mac, iOS)
- Yahoo Mail
- Outlook.com
Tools
- Litmus - Comprehensive testing platform
- Email on Acid - Cross-client testing
- Mail Tester - Spam score and rendering
- Putsmail - Send test emails
Manual Testing Checklist
- ✅ Images load correctly
- ✅ Links work
- ✅ Buttons are clickable
- ✅ Text is readable
- ✅ Layout doesn’t break
- ✅ Renders on mobile
- ✅ Works with images disabled
- ✅ Passes spam filters
Best Practices
✅ Keep width under 600px - Most email clients limit width ✅ Use inline CSS - External styles are stripped ✅ Include alt text - Images are often blocked ✅ Test extensively - Email clients vary wildly ✅ Provide plain text version - Some users prefer it ✅ Include unsubscribe link - Required by law ✅ Use web-safe fonts - Custom fonts don’t work everywhere ✅ Avoid background images - Unreliable support
Common Mistakes
❌ Using div-based layouts - Tables are more reliable ❌ External CSS files - Won’t load ❌ JavaScript - Completely blocked ❌ Forms - Don’t work in email ❌ Video embeds - Link to video instead ❌ Complex CSS - Flexbox, Grid don’t work ❌ Assuming modern features - Stick to basics
Accessibility
- Use semantic HTML where possible
- Include descriptive alt text
- Ensure good color contrast
- Use readable font sizes (14px minimum)
- Make clickable areas large enough
- Provide plain text alternative
- Test with screen readers
Legal Requirements
Include These Elements
- Physical mailing address
- Clear unsubscribe link
- Accurate “From” name
- Honest subject line
- Company identification
Privacy Compliance
- GDPR (Europe)
- CAN-SPAM (USA)
- CASL (Canada)
- Get explicit consent
- Honor opt-outs immediately
Keep Learning
- HTML Forms Tutorial - Form basics
- Responsive Design Guide - Mobile optimization
- Web Performance - Optimization tips
- Explore Templates - See working examples
Try building email templates in the htmlEditor.net playground today!
HTML email is challenging, but with the right techniques and thorough testing, you can create beautiful emails that work everywhere. Start simple, test often, and always think about the constraints of email clients.