Creating a Future-Proof Responsive Email Without Media Queries by Nicole Merlin

In notebook:
Article Notes
Created at:
2016-02-17
Updated:
2016-02-18
Tags:
email
Creating a Future-Proof Responsive Email Without Media Queries - Envato Tuts+ Web Design Tutorial

Some of the problems

  • Gmail on iOS and Android doesn't support media queries. 
  • you cannot target all possible devices with media queries
  • you can't ​align="left"​ and ​align="right"​ tables, they won't be vertically centered

The starting html document

  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<!-- NOTE: this doctype is still the safest -->
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
	<!--[if !mso]><!-->
	    <!-- NOTE: Hidden from Ms Outlook, targeting Windows Phones -->
	    <!-- NOTE: Windows Live would not show images -->
		<meta http-equiv="X-UA-Compatible" content="IE=edge" />
	<!--<![endif]-->
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<!-- NOTE: empty title - for Android clients -->
	<title></title>
	<link rel="stylesheet" type="text/css" href="styles.css" />
	<!--[if (gte mso 9)|(IE)]>
	<!-- NOTE: again targeting Outlook versions -->
	<style type="text/css">
		table {border-collapse: collapse;}
	</style>
	<![endif]-->
</head>
<body>
    <!--NOTE: body will be stripped by the servers, use 'center' element for CSS hooks -->
	<center class="wrapper">
	    <!-- NOTE: webkit for older mail clients, like Apple Mail 6, to add support for max-width CSS rule -->
		<div class="webkit">
			[content goes here]
		</div>
	</center>
</body>
</html>

Then the starting CSS

  /* Basics */
body {
    /* NOTE: margin:0 for Android Kitkat */
    margin: 0 !important;
    padding: 0;
    background-color: #ffffff;
}
/* NOTE: cellpadding and cellspacing could be added inline (cellpadding, cellspacing, but easier to maintain here */
table {
    border-spacing: 0;
    font-family: sans-serif;
    color: #333333;
}
td {
    padding: 0;
}
img {
    border: 0;
}
/* NOTE: remove unwanted padding Android 4.4 */
div[style*="margin: 16px 0"] { 
    margin:0 !important;
}
.wrapper {
    width: 100%;
    /* NOTE: center content in Yahoo mail */
    table-layout: fixed;
    /* NOTE: stop text resizing errors */
    -webkit-text-size-adjust: 100%;
    -ms-text-size-adjust: 100%;
}
/* NOTE: for Apple Mail 6 and Outlook 2011 */
.webkit {
    /* NOTE: set max width to your preferred width */
    max-width: 600px;
    /* NOTE: center in Yahoo mail*/
    margin: 0 auto;
}

Add outside container for Outlook

This would go into ​[content goes here]​ above
Outlook doesn't support ​max-width​ so we need to add an outlook-only container, with conditional comments.
A good inliner tool should add cellpadding="0" cellspacing="0" border="0"​ to these conditional tables – or add them manually yourself.
  <!--[if (gte mso 9)|(IE)]>
<table width="600" align="center">
<tr>
<td>
<![endif]-->
<table class="outer" align="center">
<tr>
		<td>
			[content goes here]
		</td>
	</tr>
</table>
<!--[if (gte mso 9)|(IE)]>
</td>
</tr>
</table>
<![endif]-->
Give the table a ​max-width​ with css and center it for Yahoo in Chrome
  .outer {
    /* NOTE: a hack so Outlook.com won't strip it out (Margin:)*/
Margin: 0 auto;
	width: 100%;
	max-width: 600px;
}

Full-width Banner Image

This would go into ​[content goes here]​ above (in table.outer)
  <table class="outer" align="center">
	<tr>
		<td class="full-width-image">
		    <!-- NOTE: pixel width for Outlook -->
			<img src="images/header.jpg" width="600" alt="" />
		</td>
	</tr>
</table>
Add CSS so that the image will resize in clients other than Outlook.
Match the pixel size, set elsewhere
  .full-width-image img {
	width: 100%;
	max-width: 600px;
	height: auto;
}

Single Column Layout

  <tr>
    <td class="one-column">
		<table width="100%">
			<tr>
				<td class="inner contents">
				    <!-- NOTE: can use <p> because of Margin: 0 auto; hack above -->
				    <!-- NOTE: better to use h1 classname than h1 tag -->
					<p class="h1">Lorem ipsum dolor sit amet</p>
					<p>Maecenas sed ante pellentesque, posuere leo id, eleifend dolor. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Praesent laoreet malesuada cursus. Maecenas scelerisque congue eros eu posuere. Praesent in felis ut velit pretium lobortis rhoncus ut erat.</p>
				</td>
			</tr>
		</table>
	</td>
</tr>
Corresponding CSS
  .inner {
    padding: 10px;
}
/*  NOTE: Margin hack   */
p {
	Margin: 0;
}
a {
	color: #ee6a56;
	text-decoration: underline;
}
.h1 {
	font-size: 21px;
	font-weight: bold;
	Margin-bottom: 18px;
}
.h2 {
	font-size: 18px;
	font-weight: bold;
	Margin-bottom: 12px;
}

/* One column layout */
.one-column .contents {
	text-align: left;
}
.one-column p {
	font-size: 14px;
	Margin-bottom: 10px;
}

Two-column Layout

  <tr>
<td class="two-column">
		<!--[if (gte mso 9)|(IE)]>
		<table width="100%">
		<tr>
		<td width="50%" valign="top">
		<![endif]-->
		[column to go here]
		<!--[if (gte mso 9)|(IE)]>
		</td><td width="50%" valign="top">
		<![endif]-->
		[column to go here]
		<!--[if (gte mso 9)|(IE)]>
		</td>
		</tr>
		</table>
		<![endif]-->
	</td>
</tr>
A column has to follow this structure:
  <div class="column">
    <table width="100%">
		<tr>
			<td class="inner">
				[content goes here]
			</td>
		</tr>
	</table>
</div>
NOTE on the wrapper .column div: you could ​display: inline-block;​ directly to the ​table​ element, but then you would not be able to nest more tables inside if needed.
And the corresponding CSS:
  /*Two column layout*/
.two-column {
text-align: center;
	font-size: 0;
}

.two-column .column {
    width: 100%;
    /* NOTE: set this to half of you base size */
	max-width: 300px;
	display: inline-block;
	/* NOTE: you can use "top", "center", "bottom" */
	/* NOTE: match this with the valign attribute on the table */
	vertical-align: top;
}

You can fill a column like so

Column size is 300px with 10px on either side, so the image size 280px
  <table class="contents">
	<tr>
			<td>
					<img src="images/two-column-01.jpg" width="280" alt="" />
			</td>
	</tr>
	<tr>
			<td class="text">
					Maecenas sed ante pellentesque, posuere leo id, eleifend dolor. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. 
			</td>
	</tr>
</table>
And the CSS
  .contents {
width: 100%;
}

.two-column .contents {
font-size: 14px;
	text-align: left;
}
.two-column img {
	width: 100%;
	max-width: 280px;
	height: auto;
}
.two-column .text {
	padding-top: 10px;
}

Three-column Layout

You can play with the ​text-align​ property to define if the blocks should align to the center, left, right.
Column html is same as before.
  <tr>
    <td class="three-column">
		<!--[if (gte mso 9)|(IE)]>
		<table width="100%">
		<tr>
		<td width="200" valign="top">
		<![endif]-->
		[column to go here]
		<!--[if (gte mso 9)|(IE)]>
		</td><td width="200" valign="top">
		<![endif]-->
		[column to go here]
		<!--[if (gte mso 9)|(IE)]>
		</td><td width="200" valign="top">
		<![endif]-->
		[column to go here]
		<!--[if (gte mso 9)|(IE)]>
		</td>
		</tr>
		</table>
		<![endif]-->
	</td>
</tr>
The CSS:
  /*Three column layout*/
.three-column {
	text-align: center;
	font-size: 0;
	padding-top: 10px;
	padding-bottom: 10px;
}
.three-column .column {
	width: 100%;
	max-width: 200px;
	display: inline-block;
	vertical-align: top;
}
.three-column .contents {
	font-size: 14px;
	text-align: center;
}
.three-column img {
	width: 100%;
	max-width: 180px;
	height: auto;
}
.three-column .text {
	padding-top: 10px;
}
The html for a three column layout is slightly different than for the two columns.

You can add more three column rows inside the ​td.three-column​ by adding multiple rows. I mispel a 
  <tr>
    <td class="three-column">
		<!--[if (gte mso 9)|(IE)]>
		<table width="100%">
		<tr>
		<td width="200" valign="top">
		<![endif]-->
		[column to go here]
		<!--[if (gte mso 9)|(IE)]>
		</td><td width="200" valign="top">
		<![endif]-->
		[column to go here]
		<!--[if (gte mso 9)|(IE)]>
		</td><td width="200" valign="top">
		<![endif]-->
		[column to go here]
		<!--[if (gte mso 9)|(IE)]>
		</td>
		</tr>
		<tr>
		<td width="200" valign="top">
		<![endif]-->
		[column to go here]
		<!--[if (gte mso 9)|(IE)]>
		</td><td width="200" valign="top">
		<![endif]-->
		[column to go here]
		<!--[if (gte mso 9)|(IE)]>
		</td><td width="200" valign="top">
		<![endif]-->
		[column to go here]
		<!--[if (gte mso 9)|(IE)]>
		</td>
		</tr>
		</table>
		<![endif]-->
	</td>
</tr>