A solid, 12 column responsive grid for emails

Pine's twelve-column responsive grid system gives you the flexibility to create layouts of all shapes and sizes, for both desktop and mobile. Create solid desktop emails and adapt them to specific mobile requirements with our utility classes.

Pine 12 column email grid

The grey columns in the image above show available content area width.

You could remove the column gutters and have more space - here's the same grid depicting column widths with gutters included:

Pine 12 column email grid with gutters included


Rows are 100% wide, center-aligned stackable tables that go inside a container and house your column tables. Their maximum width is constrained by the container, so we can take advantage of that and use width="100%" on them. This way, we don't need to worry about resetting widths through CSS when nesting rows:

<table cellpadding="0" cellspacing="0" role="presentation" width="100%">
    <td style="padding: 0 20px;">
      <table cellpadding="0" cellspacing="0" role="presentation" width="100%">
          <td class="col" width="640" style="padding: 0 10px;">

            Add your content here


Row tables have 30px padding set on both sides of their table cell. This creates the impression that the container has padding (in fact, it does not), all while giving us opt-in flexibility: the goal here is to give content some breathing room in the container, by creating whitespace.

However, we now have the freedom to choose whether we use this whitespace or not. For example, in case we need an image to stick to the side, we can remove row padding along with the column's padding for that side:

Apparent Container Padding

Inside the Row table, Pine nests another table that contains the grid Columns. As you can see in the example above, this nesting allows us to set container padding and column gutters independently, so that we don't always need to remember to set different paddings on the outer edges of the first and last columns in the grid.

Together, this Row padding combined with Column gutters create an apparent container padding of 30px, resulting in a nice 'boxed' layout on both mobile and desktop.

Of course, you can use any of the mobile spacing helpers on the row table cell, or on each grid column, to fine tune mobile spacing to your requirements.


Columns are the <td> tags inside the nested table of a Row table:

<td class="col" width="310" style="padding: 0 10px;">1</td>
<td class="col" width="310" style="padding: 0 10px;">2</td>

Each column has a fixed width defined through the width="" attribute, for desktop and tablets. This fixed width is set at 35px in the 12-column grid, but will be different depending on the amount of columns used.

Columns in Pine have 10px gutters, defined through inline shorthand-CSS padding for each side.

Columns on Mobile

Columns are required to use a col class, needed for normalization on mobile. This class will set the column width to 100%, and will also adjust content line-height to a smaller value, more suitable for mobile devices:

Column Widths On Mobile

If you don't want columns to stack on mobile, you can use custom column mobile width classes:

The class names follow the familiar Bootstrap 4 naming convention:

  • col - as in 'column'
  • -sm - indicates it will apply on small screens only
  • -X - number from 1 to 11: the equivalent amount of desktop columns to span
.col {
  box-sizing: border-box;
  display: inline-block!important;
  line-height: 23px;
  width: 100%!important;

.col-sm-1  {max-width: 8.33333%;}
.col-sm-2  {max-width: 16.66667%;}
.col-sm-3  {max-width: 25%;}
.col-sm-4  {max-width: 33.33333%;}
.col-sm-5  {max-width: 41.66667%;}
.col-sm-6  {max-width: 50%;}
.col-sm-7  {max-width: 58.33333%;}
.col-sm-8  {max-width: 66.66667%;}
.col-sm-9  {max-width: 75%;}
.col-sm-10 {max-width: 83.33333%;}
.col-sm-11 {max-width: 91.66667%;}

These classes use percentage-based max-width, instead of width. This way, we only constrain the mobile width, instead of overriding it with !important. Being able to write less code is always a win :)

You can use any combination of the mobile width classes. If their sum exceeds the equivalent of 12 columns, the first column that won't be able to fit in the same row will break onto the next one:

Column Offsets On Mobile

You can use offset classes to push columns to the right on mobile. These use the CSS margin-left property.

Just like mobile widths, the naming convention follows the Bootstrap 4 pattern:

  • col - as in 'column'
  • -sm - indicates it will apply on small screens only
  • -push - indicates it will push the column
  • -X - number from 1 to 11: the equivalent amount of desktop columns to span
.col-sm-push-1  {margin-left: 8.33333%;}
.col-sm-push-2  {margin-left: 16.66667%;}
.col-sm-push-3  {margin-left: 25%;}
.col-sm-push-4  {margin-left: 33.33333%;}
.col-sm-push-5  {margin-left: 41.66667%;}
.col-sm-push-6  {margin-left: 50%;}
.col-sm-push-7  {margin-left: 58.33333%;}
.col-sm-push-8  {margin-left: 66.66667%;}
.col-sm-push-9  {margin-left: 75%;}
.col-sm-push-10 {margin-left: 83.33333%;}
.col-sm-push-11 {margin-left: 91.66667%;}

You can use these classes to fine tune and adapt your layouts for mobile devices. For example, let's create a 3-column desktop layout that changes to 2+1 columns on mobile, and aligns the third column (price) with the second one (description) on mobile:

Responsive breakpoints

Pine is desktop-first.

The fixed-width container and columns are overridden for mobile devices through the use CSS media queries.

Large breakpoint

For large-ish screen sizes (i.e. landscape view), Pine resets Wrapper and Container widths to 100%, but the desktop column widths are still being used. This affects all devices with a screen size between 700px and 730px:

@media  only screen and (max-width: 730px) {
  .wrapper img {max-width: 100%;}
  u ~ div .wrapper {min-width: 100vw;}
  .container {width: 100%!important; -webkit-text-size-adjust: 100%;}

Small breakpoint

This is where the fun starts. This media query applies to most devices, up to 699px screen width:

@media  only screen and (max-width: 699px) {