Responsive Column Layouts

It can be difficult to read a multi-column email on a small screen; having to scroll horizontally is kind of a pain. Reading on small displays tends to work better if it’s done in a linear fashion, from top-to-bottom. Using media queries we can switch a multi-column layout to a single-column one, making it easier to read an email. There are two methods that will be covered here, each with its pros and cons.

Method 1 - Block-level <td> Elements

The first method uses the same column structure covered in the HTML section’s Column Layouts page. Here’s that code:

<table border="0" cellpadding="0" cellspacing="0" width="600" id="templateColumns">
    <tr>
        <td align="center" valign="top" width="50%" class="templateColumnContainer">
            <table border="0" cellpadding="10" cellspacing="0" width="100%">
                <tr>
                    <td class="leftColumnContent">
                        <img src="http://placekitten.com/g/480/300" width="280" style="max-width:280px;" class="columnImage" />
                    </td>
                </tr>
                <tr>
                    <td valign="top" class="leftColumnContent">
                        <h1>Left Column</h1>
                        Lorem ipsum dolor sit amet.
                    </td>
                </tr>
            </table>
        </td>
        <td align="center" valign="top" width="50%" class="templateColumnContainer">
            <table border="0" cellpadding="10" cellspacing="0" width="100%">
                <tr>
                    <td class="rightColumnContent">
                        <img src="http://placekitten.com/g/480/300" width="280" style="max-width:280px;" class="columnImage" />
                    </td>
                </tr>
                <tr>
                    <td valign="top" class="rightColumnContent">
                        <h1>Right Column</h1>
                        Lorem ipsum dolor sit amet.
                    </td>
                </tr>
            </table>
        </td>
    </tr>
</table>

The default styling for the columns isn’t really a concern here, so let’s skip straight to the media query styles:

<style type="text/css">
    @media only screen and (max-width: 480px){
        #templateColumns{
            width:100% !important;
        }

        .templateColumnContainer{
            display:block !important;
            width:100% !important;
        }

        .columnImage{
            height:auto !important;
            max-width:480px !important;
            width:100% !important;
        }

        .leftColumnContent{
            font-size:16px !important;
            line-height:125% !important;
        }

        .rightColumnContent{
            font-size:16px !important;
            line-height:125% !important;
        }
    }
</style>

We start off the media query stylesheet by setting the templateColumns table width to 100%, so it’ll adapt to different screen sizes or orientations. The important bit in how this layout switching works comes next: by setting each templateColumnContainer <td> to block-level elements, and reinforcing that with the 100% width declaration, the right column snaps under the left, and we have a single-column view. After that, the image gets its fluid styling and the text gets a size bump.

As we mentioned, each method has its pros and cons. This method is the most stable; by virtue of using standard, tried-and-tested coding conventions, the columns work in every client in desktop view. There are a couple of downsides, however. First is the fact that setting a <td> as a block-level element runs counter to how they’re actually supposed to be used. Second, you can’t swap the order of the columns or do any other fancy layout-shifting stuff without resorting to CSS float or position - properties that don’t enjoy wide or consistent support across email clients.

So, if your aim is stability over flexibility, this is the way to go.

Method 2 - Aligned <table> Elements

Method 2 is the opposite of the first; its strength is flexibility, but it’s not very stable. The columns are coded a little differently:

<table border="0" cellpadding="0" cellspacing="0" width="600" id="templateColumns">
    <tr>
        <td align="center" valign="top">
            <table align="left" border="0" cellpadding="10" cellspacing="0" width="300" class="templateColumnContainer">
                <tr>
                    <td class="leftColumnContent">
                        <img src="http://placekitten.com/g/480/300" width="280" style="max-width:280px;" class="columnImage" />
                    </td>
                </tr>
                <tr>
                    <td valign="top" class="leftColumnContent">
                        <h1>Left Column</h1>
                        Lorem ipsum dolor sit amet.
                    </td>
                </tr>
            </table>
            <table align="right" border="0" cellpadding="10" cellspacing="0" width="300" class="templateColumnContainer">
                <tr>
                    <td class="rightColumnContent">
                        <img src="http://placekitten.com/g/480/300" width="280" style="max-width:280px;" class="columnImage" />
                    </td>
                </tr>
                <tr>
                    <td valign="top" class="rightColumnContent">
                        <h1>Right Column</h1>
                        Lorem ipsum dolor sit amet.
                    </td>
                </tr>
            </table>
        </td>
    </tr>
</table>

Each column <table> sits within just one <td> this time, and they each get a fixed width of 300px. The most important difference is the presence of the align attribute on each table; this attribute mimics the functionality of CSS float, but it’s actually well-supported across email clients since its HTML-spec.

In the HTML, we’ve moved the class name templateColumnContainer from the <td> elements seen in the first example to both of the aligned <table> elements that make up the left and right columns. Because each <table> is essentially floated, they automatically wrap when the media query is triggered. There’s only one change required in the media query style for templateColumnContainer; we’re now targeting a <table> instead of a <td> element:

<style type="text/css">
    @media only screen and (max-width: 480px){
        .templateColumnContainer{
            display:block !important;
            width:100% !important;
        }
    }
</style>

Setting the width of each column to 100% allows them to fill the available screen space, just as in the first example. So, what’s bad about this method? Instability. Because the columns are essentially floated, they tend to wrap under one another if there’s any layout wonkiness. You’re likely to run into this problem if the column <table> elements “touch” each other, like placing two 300px-wide columns next to each other in a 600px space. It’s all dependent on how an email client renders tables or calculates widths. Making the columns a little narrower than total width of the space they live in is sometimes a suitable work-around, but it’s not 100% fool-proof.

In spite of those issues, the flexibility inherent to this method and how it allows for layout switching, which you can see covered in Layout Manipulation, is the best reason to use it.