Introduction

Premailer

Una de las cosas mas horribles de maquetar mails es la ausencia de un css, como todos (quizas) sabemos el css en los mails va inline sobre cada atributo, esto hace que el maquetado quede horrendo, desprolijo e ilegible en muchos casos (ver los mails de buenchef por ejemplo).

Por suerte existe una gema llamada premailer que, entre otras cosas, nos permite utilizar un css para maquetar nuestros mails (obviamente termina procesando el mail y metiendo las propiedades de css especificadas inline para cada elemento). Para instalarla solamente agregamos gem 'premailer-rails' a nuestro gemfile y somos felices.

Luego podemos incluir todos los css que queramos de la siguiente forma:

%link{rel: "stylesheet", href: "email"}

Esto buscara un css llamado email en cache, en public, usando el asset pipeline de rails o haciendo un request a la url especificada (en ese orden segun la documentacion de la gema).

Maquetado de mails

En esta seccion queria aprovechar para compartirles el layout y el css que use en mandapp y shipeala (robado asquerosamente de main capital si la memoria no me falla asique no vayan a pensar que lo hice yo, aunque algunos ajuste le hicimos con maxi1), ademas de algunas cositas con las que me cruce cuando hacia estas cosas medianamente seguido.

  • Si bien he visto mails maquetados "normal" que funcionan bien (en buenchef por ejemplo, de nuevo, si la memoria no me falla) lo que veo que se recomienda es maquetarlos como tablas para asegurarse que funcione en la mayor cantidad de clientes posible.

  • Basicamente cada cliente soporta las propiedades de css que se le canta, la informacion mas actualizada sobre esto que pude encontrar esta aca y la ultima actualizacion fue en mayo de 2014.

  • Mas alla del link que les pase en el bullet anterior queria compartirles mi (poquita) experiencia, que fue solo sobre gmail y outlook, generalmente gmail se banca todo lo que uno le pueda llegar a tirar (padding, margin, vertical-align, float, etc) pero outlook recuerdo que no soporta float (pero soporta vertical-align) y padding-right (si! soporta left, top y bottom pero no right!) asique si quieren flotar algo tienen que ponerle un contenedor vacio con display inline-block y width para que lo empuje, y para maquetar botones pueden usar padding top y bottom para el alto y width para el ancho.

Layout

  %head
    %link{rel: "stylesheet", href: "email"}
  %body
    %table{ style: "width:100%;" }
      %tr
        %td.container{:width => "600px"}
          .content
            %table.main{:cellpadding => "0", :cellspacing => "0", :width => "100%"}
              %tr
                = render "layouts/mailer_header"
              %tr
                %td.content-wrap
                  %table{:cellpadding => "0", :cellspacing => "0", width: "100%"}
                    %tbody.body-cm
                      %tr
                        = yield
                      %tr
                        %td
                          %br
              - unless @disable_footer
                %tr
                  = render "layouts/mailer_footer"

Css

.separator {
  margin-bottom: 40px;
  width: 520px;
  margin-left: 18px;
}

.half-separator {
  width: 200px;
}

.background-gray {
  background: #E6E6E6;
}

.background-darkgray {
  background: #CCCCCC;
}

.blue {
  color: #51c0ff;
}

.green {
  color: #57C07B;
}

.banner{
  max-width: 560px
}

hr {
  border: 1px solid #EAEAEA;
}

.btn-center{
  text-align: center;
  margin-left: 37% !important;
}

.btn-primary{
  background: #99cc33;

  a{
    color: #ffffff;
    font-weight: bold;
    text-decoration: none;
  }
}

.darkblue-bg {
  background-color: #1c84c6!important;
  color: #FFF;
}

.text-navy {
  color: #1ab394;
  text-decoration: none;
}

.vertical-container {
  width: 90%;
  max-width: 1170px;
  margin: 0 auto;
}

.vertical-container::after {
  content: "";
  display: table;
  clear: both;
}

.bold{
  font-weight: bold;
}

.vertical-date small {
  color: #1ab394;
  font-weight: 400;
}

.lightblue-bg {
  background-color: #1c84c6;
  color: #ffffff;
}

.orange-bg {
  background-color: #ffaf30;
  color: #ffffff;
}

.green-bg {
  background-color: #73C795;
  color: #ffffff;
}

/* -------------------------------------
    GLOBAL
    A very basic CSS reset
------------------------------------- */
* {
    margin: 0;
    padding: 0;
    font-family: "Helvetica Neue", "Helvetica", Helvetica, Arial, sans-serif;
    box-sizing: border-box;
    font-size: 14px;
}

img {
    max-width: 100%;
}

body {
    -webkit-font-smoothing: antialiased;
    -webkit-text-size-adjust: none;
    width: 100% !important;
    height: 100%;
    line-height: 1.6;
}

/* Let's make sure all tables have defaults */
table td {
    vertical-align: top;
}

/* -------------------------------------
    BODY & CONTAINER
------------------------------------- */
body {
    background-color: #f6f6f6;
}

.body-wrap {
    background-color: #f6f6f6;
    width: 100%;
}

.container {
    display: block !important;
    max-width: 600px !important;
    margin: 0 auto !important;
    /* makes it centered */
    clear: both !important;
}

.content {
    max-width: 600px;
    margin: 0 auto;
    display: block;
    padding: 20px;      
}

.blue-btn {
  padding: 10px;
  font-size: 14px;
  text-transform: uppercase;
  text-align: center;
  display: block;
  border-radius: 0;
  background: #51c0ff;
  color: white;
  border-radius: 0px;
  border: 1px solid transparent;
  white-space: nowrap;
  text-decoration: none;
  width:220px;
  &:hover {
      background: #12A0F1;
      color: white;
  }
}

.orange-btn {
  padding: 5px;
  font-size: 14px;
  text-transform: uppercase;
  text-align: center;
  display: block;
  border-radius: 0;
  background: #FFA500;
  color: white;
  border-radius: 0px;
  border: 1px solid transparent;
  white-space: nowrap;
  text-decoration: none;
  width:180px;
  &:hover {
      background: #12A0F1;
      color: white;
  }
}

.orange {
  color: #FFA500;
}

.link {
  margin-left: 140px;
  margin-top: 40px;
}

/* -------------------------------------
    HEADER, FOOTER, MAIN
------------------------------------- */
.main {
    background: #fff;
    border: 1px solid #e9e9e9;
    border-radius: 3px;
    /*background: #EAEBED;*/
}

.content-wrap {
    padding: 20px;
}

.content-block {
    padding: 0 0 10px;
}

.header {
  width: 100%;
  padding: 10px 0px;
  background: black;
  text-align: center;
}

.footer{
  text-align: center;
}  

.footer-text{
  display: inline-block;
  margin-bottom: 30px;
}

.footer-image {
  display: inline-block;
  margin-right: 20px;
  vertical-align: top;
}

.blue-line {
  height: 10px;
  background: #52C0FF;
}

/* -------------------------------------
    TYPOGRAPHY
------------------------------------- */
h1, h2, h3 {
    font-family: "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif;
    color: #000;
    margin: 40px 0 0;
    line-height: 1.2;
    font-weight: 400;
}

h1 {
    font-size: 32px;
    font-weight: 500;
}

h2 {
    font-size: 24px;
}

h3 {
    font-size: 18px;
}

h4 {
    font-size: 14px;
    font-weight: 600;
}

p, ul, ol {
    margin-bottom: 10px;
    font-weight: normal;
}
p li, ul li, ol li {
    margin-left: 5px;
    list-style-position: inside;
}

/* -------------------------------------
    LINKS & BUTTONS
------------------------------------- */
a {
    color: #1ab394;
    text-decoration: underline;
}

.btn-primary, .btn-action {
    background: #73aa38;
    padding: 10px 20px;
    color: white;
    margin: 20px 0px;
    cursor: pointer;
    transition: 0.3s ease;
    webkit-transition: 0.3s ease;
    display: inline-block;
    font-weight: normal;
    font-size: 14px;
    text-align: center;
    text-decoration: none;
    line-height: 1.42857143;
    vertical-align: middle;
    ms-touch-action: manipulation;
    touch-action: manipulation;
    background-image: none;
    border: 1px solid transparent;
    border-radius: 4px;
    white-space: nowrap;
    webkit-user-select: none;
    moz-user-select: none;
    ms-user-select: none;
    user-select: none;
}
.btn-primary:first-letter, .btn-action:first-letter {
  text-transform: capitalize;
}

/* -------------------------------------
    OTHER STYLES THAT MIGHT BE USEFUL
------------------------------------- */
.last {
    margin-bottom: 0;
}

.first {
    margin-top: 0;
}

.aligncenter {
    text-align: center;
}

.alignright {
    text-align: right;
}

.alignleft {
    text-align: left;
}

.clear {
    clear: both;
}

.inline-block {
  display: inline-block;
}

/* -------------------------------------
    ALERTS
    Change the class depending on warning email, good email or bad email
------------------------------------- */
.alert {
    font-size: 16px;
    color: #fff;
    font-weight: 500;
    padding: 20px;
    text-align: center;
    border-radius: 3px 3px 0 0;
}
.alert a {
    color: #fff;
    text-decoration: none;
    font-weight: 500;
    font-size: 16px;
}
.alert.alert-warning {
    background: #f8ac59;
}
.alert.alert-bad {
    background: #ed5565;
}
.alert.alert-good {
    background: #1F4E79;
}

/* -------------------------------------
    RESPONSIVE AND MOBILE FRIENDLY STYLES
------------------------------------- */
@media only screen and (max-width: 640px) {
    h1, h2, h3, h4 {
        font-weight: 600 !important;
        margin: 20px 0 5px !important;
    }

    h1 {
        font-size: 22px !important;
    }

    h2 {
        font-size: 18px !important;
    }

    h3 {
        font-size: 16px !important;
    }

    .container {
        width: 100% !important;
    }

    .content, .content-wrap {
        padding: 10px !important;
    }

    .invoice {
        width: 100% !important;
    }
}

Last updated