<table>s are still the most dependable way to create layouts for HTML emails.

<table role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%">
    <td> … </td>
    <td> … </td>
Column 1 Column 2
role="presentation"Tells screen readers to skip over the table’s tags and move straight into the content.
cellspacing="0"Negates unwanted spacing
cellpadding="0"Negates unwanted padding
border="0"Negates unwanted borders
width="100%"(Optional) Forces table take up all available horizontal space.


The best way to control spacing between components in HTML email is to use padding (applied to <td>’s) and margin (applied to <h> tags, <p>’s, <ol>’s, <li>’s, etc.).

However padding and margin cannot be used reliably to space out <table>’s or <tr>’s. In these cases, it's best to use a spacer to create separation.

  <td aria-hidden="true" height="30" style="font-size: 0; line-height: 0px;">
heightSize of the spacer.
aria-hidden="true"Hide the &nbsp; from screen readers.
&nbsp;Some email clients will collapse the spacer’s height if there’s no content.
style="font-size: 0px;line-height: 0px;"Some clients will add additional space inherited from the &nbsp;’s font-size and line-height.


It’s safe and accessible to use semantic HTML tags like <h><p>, and <ul> for text in email just as we do for the web. The main difference in email is that CSS should be written inline to specify intended styles (like the color of an anchor tag) and zero out unintended defaults (like the default margin around a <p> tag).


<h1 style="">Heading level 1</h1>
<h2 style="">Heading level 2</h2>
<h3 style="">Heading level 3</h3>
Heading 1 Heading 2 Heading 3


<p style="">Paragraph text</p>
<p style="">More paragraph text</p>

Paragraph text lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer varius eros suscipit, tincidunt leo eget, consequat libero.

More paragraph text


<ul style="padding: 0; margin: 0 0 15px 0; list-style-type: disc;">
  <li style="margin: 0 0 10px 30px;">Unordered list item</li>
  <li style="margin: 0 0 10px 30px;">Unordered list item</li>
  <li style="margin: 0 0 10px 30px;">Unordered list item</li>
<ol style="padding: 0; margin: 0 0 15px 0; list-style-type: decimal;">
  <li style="margin: 0 0 10px 30px;">Ordered list item</li>
  <li style="margin: 0 0 10px 30px;">Ordered list item</li>
  <li style="margin: 0 0 10px 30px;">Ordered list item</li>
  • Unordered list item
  • Unordered list item
  • Unordered list item
  1. Ordered list item
  2. Ordered list item
  3. Ordered list item
<a href="" style="color: teal;">Link text</a>

Some email clients auto-detect certain text strings (like dates, times, and locations) and automatically convert them into hyperlinks. We can’t remove the link, but we can make the link appear like the text around it by negating a few CSS styles.

  a[x-apple-data-detectors],  /* iOS */
  .aBn,  /* Gmail */
  .unstyle-auto-detected-links a {
    border-bottom: 0 !important;
    cursor: default !important;
    color: inherit !important;
    text-decoration: none !important;
    font-size: inherit !important;
    font-family: inherit !important;
    font-weight: inherit !important;
    line-height: inherit !important;
<p class="unstyle-auto-detected-links">
  Our mailing address is 123 Fake St.

Our mailing address is 123 Fake St.

The mail address is a link ☝️

In this example, some email clients will detect "123 Fake St." as a location and automatically add an unstyled <a href=""> tag that links to a maps product like Google Maps or Apple Maps. We can't prevent this from happening, but we can make the link appear like the surrounding body text by including a unstyle-auto-detected-links class in the container tag.

Prevent Text Wrapping

A non-breaking space (&nbsp;) can be used to prevent a group of words from breaking onto multiple lines. Useful for keeping names together and preventing typographic orphans and widows.

 I want these&nbsp;words to stay together and prevent&nbsp;widows.

🙏 Rob Berinti’s TEDC ’15 talk on Typography

Web fonts

Sometimes we use web fonts in emails to match the aesthetic of a marketing campaign or announcement. Web fonts don’t have great support in email clients, so here’s how we ensure our web font displays in as many email clients as possible:

  1. Include an external stylesheet at the top of the email’s <head> tag. Sites like Google Fonts provide this code.
  2. Windows Outlook sometimes chokes on web font references and defaults everything to Times New Roman. To avoid this, wrap the web font reference in a <!--[if !mso]> tag (so Windows Outlook ignores it) and define a fallback font for Windows Outlook inside a <!--[if mso]> tag.
  3. Lastly, reference the web font at the beginning of the font stack, followed by a system fallback font for email clients that can’t display (and ignore) the web font.
  <!--[if mso]>
    * {
      font-family: sans-serif !important;
  <!--[if !mso]>
  <link href='' rel='stylesheet' type='text/css'>
  <p style="font-family: 'Lobster', cursive;">Text in Lobster in email clients that support web fonts.</p>

Text in Lobster in email clients that support web fonts.

But seriously please don't actually use Lobster in your email, I'm just trying to show how web fonts work.


All email clients can display .png.gif, and .jpg images displayed with the <img> tag. .svg images are not well supported, regardless of how they’re referenced, so avoid using these.

Most images should be coded responsive by default, meaning they’ll scale down proportionately in small viewports. It’s safest to code all images this way, even if they don’t end up scaling in practice. However if we’re confident that an image will never scale, we can display a non-responsive image using less code.

<!-- Responsive -->
<img src="" width="640" height="" alt="alt_text" border="0" style="width: 100%; max-width: 640px; height: auto; display: block;" class="g-img">
<!-- Static -->
<img src="" width="128" height="128" alt="alt_text" border="0" style="display: block;">

srcattributeUse full https:// absolute path reference.
heightattributeSet to intended desktop width.
widthattributeOptional. Use only for images that won’t scale.
borderattributeAlways set to 0 to avoid blue outlines on image links.
altattributeAlways include but can be left empty if image is ornamental (Eg. alt="").
widthinline CSS[Responsive] Always set to 100% for responsive images. Optional for static images.
max-widthinline CSS[Responsive] Always set to intended desktop width. Optional for static images.
heightinline CSS[Responsive] Always set to auto for responsive images. Optional for static images.
displayinline CSSGenerally good practice to use display:block; when possible since it negates a few pixels of unwanted space below images in some clients.
.g-imgclassAdvisable for images larger than ~300px wide. Prevents gmail from displaying an image download icon over images.


Background Colors

Solid background colors are very well supported in email clients using the bgcolor attribute, or background-color or background CSS properties.

<!-- Using HTML attributes -->
<table bgcolor="#9C36B5">
    <td> … </td>
<!-- Using inline CSS -->
<table style="background-color: #9C36B5;">
    <td> … </td>
My text

Background Images

Background images allow us to place additional HTML content on top of them, one of the few reliable ways to provide layering possibilities in email. A benefit of using background images over foreground images is, when paired with a background color, the HTML content on top of the background image remains accessible even when images are disabled.

Background images can be complicated to implement in email, as many properties need to be defined once in CSS and again in VML for Windows Outlook and Win10 Mail.

<td valign="middle" style="background-image: url(''); background-position: center center; background-size: cover; background-color: #000000;">
    <!--[if gte mso 9]>
    <v:rect xmlns:v="urn:schemas-microsoft-com:vml" fill="true" stroke="false" style="width:680px;height:220px;">
    <v:fill type="tile" src="" color="#000000"/>
    <v:textbox inset="0,0,0,0">
      <table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation">
          <td style="padding: 60px; color: #ffffff; font-family: arial, sans-serif; font-size: 15px; text-align: center;">
            Foreground HTML content.
    <!--[if gte mso 9]>
My text
background-imageinline CSSAlways set and use full https:// reference.
background-positioninline CSSOptional to set the size of the image.
background-sizeinline CSSOptional to set the position of the image.
background-colorinline CSSAlways set to make foreground HTML legible if background image doesn’t load.
widthVML in <v:rect>Always set to full container width. VML doesn’t account for padding, adjust as necessary.
heightVML in <v:rect>Always set to full container height. VML doesn’t account for padding, adjust as necessary.
srcVML in <v:fill>Always set and use full https:// reference.
colorVML in <v:fill>Always set to make foreground HTML legible if background image doesn’t load.


Buttons are the primary way for users to take action from an email. Buttons should have ample click / tap space and describe their actions. Creating a button that displays consistently across email clients requires multiple HTML tags.

  .button-td-primary:focus {
    background: #555555 !important;
<table align="center" role="presentation" cellspacing="0" cellpadding="0" border="0" style="margin: auto;">
    <td class="button-td button-td-primary" style="border-radius: 4px; background: #222222;">
      <a class="button-a button-a-primary" href="" style="background: #222222; border: 1px solid #000000; font-family: sans-serif; font-size: 15px; line-height: 15px; text-decoration: none; padding: 13px 17px; color: #ffffff; display: block; border-radius: 4px;">Primary Button</a>
Button Text
.button-tdProvides transition effects on :hover where supported.
.button-aProvides transition effects on :hover where supported.
.button-td-primaryAlso provides :hover and dark mode styles where supported.
.button-a-primaryAlso provides :hover and dark mode styles where supported.