How to Send Tailwindcss-Styled Emails With Ruby on Rails 7

Oct 7, 2022 - 6 min read
How to Send Tailwindcss-Styled Emails With Ruby on Rails 7
Share

Have you ever tried to create a good looking email design from scratch? Or how about using TailwindCSS to write your email layouts?

Well, if you did, you've probably failed. A lot. And it's safe to say reminding you about it not a good way to make friends.

But! I'm here to help.

Let me show you how I create beautiful email templates in just a few minutes and how I use them in my Rails projects.

Here's a video version of this article if you prefer to watch instead.

But first, let's talk about why creating good-looking email templates is hard.

One of the reasons is... there's no HTML standard for emails, so different email clients render these layouts differently.

While web browsers have come a long way in the past decade in terms of standards and CSS support, email clients, well... not so much.

As part of my Practical Ruby on Rails For Beginners course, I recently tried building an HTML layout for one of the lessons I teach.

And because I was already using TailwindCSS in that particular project, I thought I could use it in my mailer layout as well. But that's when things started to become frustrating.

You see, the problem with email design is you can't use the same DIV-based markup that you use for browser layouts, you've gotta use HTML tables. It's like doing web design in the Internet Explorer 6 era.

And if you don't know what that is, consider yourself lucky.

But on top of that, you have to inline your CSS, and there are many small differences between email clients as far as CSS support goes.

Some of the most popular email clients go as far as blocking images altogether for security reasons.

So the way I see it is, you have three options.

The first option is to dive deep, create your layout from scratch and use an email testing service to make sure your emails look good across multiple email clients.

The second option is to use an email design service and purchase one of their done-for-you templates. This will save you a ton of time, and it's totally worth it if you ask me.

And the third option, which is also the topic of this article, is a little bit of both.

You start with a basic template, and you use TailwindCSS to customize the design.

And the magic tool that lets you do that is called Maizzle. It's an open-source framework for building HTML email layouts using TailwindCSS.

You clone the starter repository by following the installation instructions on their website.

npx degit maizzle/maizzle email_template
cd email_template
npm install
npm run dev

And this will give you two URLs you can use. The first one (port 3001) takes you to a dashboard, and the second one takes you to a folder where you can chose a template you want to see.

Here's what the transactional template looks like.

Ruby on Rails email template TailwindCSS

It's not much, but it's a good starting point. And the best part is... you can customize this layout using TailwindCSS.

So let's see how that works.

If you open up the transactional.html template in a text editor, you'll see the HTML looks a bit weird. That's because it's a table-based layout (like we used to build more a decade ago, when Internet Explorer 6 was popular) instead of a div-based layout like you're probably used to.

And there are some strange-looking tags in there like the <outlook /> tag, and even some new TailwindCSS classes (like the mso-text-raise) for targeting different email clients. Those come from the tailwind-email-variants package.

Component-based layout

What's even cooler is you can create a bunch of reusable layout components that you can plug in or out of your various templates (e..g, footers, banners, etc.).

There's components folder where you can add your own components.

To illustrate how this works, I'll add a new test-component.html to that folder.

<!-- src/components/test-component -->
Hey This Is a Test

And to use it in the layout, I'll simply add a <component /> tag.

<!-- templates/transactional.html -->
<component src="src/components/test-component.html"></component>

You can make that path shorter if you add the path to all your components in the config file. This is documented in the Maizzle docs.

And if you have some content inside of this component tag, like "ABC123", you have access to that content via a <content /> tag, inside of your component.

<!-- src/components/test-component -->
Hey This Is a Test
<content></content>

Import the template into your Rails app

Ok so let's say we have designed our template using Maizzle, and we're ready to use it. How do we use this in Rails?

Well... you can build the HTML of the template using npm run build.

Once that's done, you can take the generated HTML from the build_production folder, and copy it over into your Rails project.

In the project I was building for my course, I've pasted this template in the mailer.html.erb layout.

Here, I have a UserMailer class with a hello method, and a corresponding hello.html.erb template.

# app/mailers/user_mailer.rb
class UserMailer < ApplicationMailer
  def hello
    @user = params[:user]
    attachments["flower.png"] = File.read("tmp/flower.png")
    mail(to: email_address_with_name(@user.email, @user.name), subject: "Hello #{@user.name}")
  end
end
<!-- app/views/user_mailer/hello.html -->
<p>
  Hello <%= @user.name %>,
</p>
<p style="margin: 0; margin-bottom: 24px">
  Go to the website by clicking the button below.
</p>
<div style="line-height: 100%">
  <a href="<%= root_url %>" class="hover-bg-indigo-500" style="text-decoration: none; display: inline-block; border-radius: 4px; background-color: #4338ca; padding-top: 14px; padding-bottom: 14px; padding-left: 16px; padding-right: 16px; text-align: center; font-size: 16px; font-weight: 600; color: #fff">
    <!--[if mso]>
      <i style="mso-text-raise: 30px; letter-spacing: 24px">&#8202;</i>
    <![endif]-->
    <span style="mso-text-raise: 16px">Click this &rarr;</span>
    <!--[if mso]>
      <i style="letter-spacing: 24px">&#8202;</i>
    <![endif]-->
  </a>
</div>

Inside the template, I've pasted the body of the email, and I've added Rails specific things like the user's name here, and the root url.

And I've done that for the layout as well. As you can see, I'm using a link to my website, and a generated logo url.

<!-- app/views/layouts/mailer.html.erb -->
<a href="https://mixandgo.com">
  <img src="<%= image_url('logo.png') %>" width="70" alt="Mix & Go Logo" style="border: 0; max-width: 100%; vertical-align: middle">
</a>

And this is what the email preview looks like.

Ruby on Rails email template TailwindCSS preview

So that's how I'm building my Rails email templates using TailwindCSS.

If you enjoyed this post, please share some love (like and/or retweet) on this tweet.

12 Project Ideas
Cezar Halmagean
Software development consultant with over a decade of experience in helping growing companies scale large Ruby on Rails applications. Has written about the process of building Ruby on Rails applications in RubyWeekly, SemaphoreCI, and Foundr.