Tailwind CSS : How To Send Emails In Laravel

Hello Geek, Tailwind CSS is an excellent tool for creating visually appealing websites and apps. And Laravel is one of the best frameworks for quickly creating complete applications.

Creating HTML- or Blade-templates for e-mails is always a hassle. E-mail clients, as you may know, do not support separate stylesheets. This means that you must include all of your CSS inline in each email template. That must be extremely unpleasant, right?

If you are a seasoned developer (or not yet), you should consider using Tailwind CSS in Laravel e-mail templates as well. Fortunately, I discovered an easy way to add Tailwind CSS to your Laravel template emails.

How to create Laravel email templates with Tailwind CSS

The process for using Tailwind CSS in Laravel e-mails is a simple four-step proces:

  1. Create an e-mail template and use Tailwind CSS in the template.
  2. Create a separate CSS-file (mail.css) and run Tailwind CSS with a separate config.
  3. Let the e-mail template extend a base HTML-template.
  4. Inline the Tailwind CSS using a CSS inliner.

Create a Blade-file

To begin, we’ll need to create the Blade-file for our email template. Create a new directory called mails in your resources/views directory, with the file order-created.blade.php inside (of course, you can use a custom name).

You can include some simple Blade-code in this file:

<div>
    <h1 class="text-4xl tracking-tight font-bold">My title!</h1>
    <!-- More code -->
</div>

Create a Laravel Mail class

Next, create a new Mail class with the following artisan command:

php artisan make:mail OrderCreated

This will result in the creation of the following file in your project. In the build() function, change the name of the view to the name of the file you created above:

<?php
 
namespace App\Mail;
 
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
 
class OrderCreated extends Mailable
{
    use Queueable, SerializesModels;
 
    /**
     * Create a new message instance.
     *
     * @return void
     */
    public function __construct()
    {
        //
    }
 
    /**
     * Build the message.
     *
     * @return $this
     */
    public function build()
    {
        return $this->view('mails.order-created');
    }
}

Create a special `mail.css` file with Tailwind CSS

Make a new mail.css file in your resources/css directory. You can also name the file something else.

This CSS file will include the Tailwind classes for all of your emails. You don’t need a separate CSS file for each email template because all of the styles will be inlined anyway.

Insert the following code into the mail.css file:

@tailwind base;
@tailwind components;
@tailwind utilities;

Following that, we must create a separate Tailwind CSS configuration file for our emails. Make a file called tailwind-mail.config.js in the root of your project.

Please change the content key to only scan the files in resources/views/mails/*/.blade.php. The rest of the file is up to you to configure, but here’s an example from me:

const defaultTheme = require('tailwindcss/defaultTheme');
const colors = require('tailwindcss/colors')
 
module.exports = {
    content: [
        './resources/views/mails/**/*.blade.php',
    ],
    theme: {
        screens: {
            'xxs': '375px',
            'xs': '475px',
            ...defaultTheme.screens,
        },
        fontFamily: {
            'sans': ['"DM Sans"', 'system-ui'],
            'filament': ['DM Sans', ...defaultTheme.fontFamily.sans],
            'serif': ['Georgia', 'ui-serif'],
            'display': ['"PP Eiko"', 'system-ui'],
            'mono': ["JetBrains Mono", 'monospace']
        },
        extend: {
            colors: {
                danger: colors.rose,
                primary: colors.sky,
                success: colors.lime,
                warning: colors.yellow,
            },
        },
    },
    plugins: [
        require('@tailwindcss/forms'),
        require('@tailwindcss/typography'),
    ],
}

Next, you should update your webpack.mix.js file and update the file to the following:

const mix = require('laravel-mix');
/* Add this line to the top if you do not have this: */
const tailwindcss = require('tailwindcss');
 
mix.js('resources/js/app.js', 'public/js')
    .postCss('resources/css/app.css', 'public/css', [
        require("tailwindcss")
    ])
    /* Add the next three lines: */
    .postCss('resources/css/mail.css', 'public/css', [
        tailwindcss('tailwind-mail.config.js')
    ])
    .version();

If you already don’t have Tailwind CSS installed in Laravel follow the official guide on the Tailwind CSS website.

Create a Blade-component with the base layout

The next thing we should do, is create a sort of base Blade-template that every individual Laravel e-mail template uses. The equivalent of the layouts/app.blade.php file, but now for e-mails.

I’ll create this as a view component, meaning that we create a Blade and PHP file.

I created a resources/mails/base.blade.php template, but you are free to choose your own location. Add the following contents:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
 
    <!-- The CSS stylesheet which will be inlined. -->
    <link rel="stylesheet" type="text/css" href="{{ mix('css/mail.css') }}">
 
    @if($subject = $attributes->get('subject'))
        <title>{{ $subject }}</title>
    @endif
</head>
<body>
    <div class="w-full h-full px-8 py-12">
        {{ $slot }}
    </div>
</body>
</html>

Next, create a PHP-file in the app/View/Components folder (or somewhere else). Add the following contents:

<?php
 
namespace App\View\Components;
 
use Illuminate\Contracts\View\View;
use Illuminate\View\Component;
 
class Base extends Component
{
    public function render(): View
    {
         // Update the name of your view.
        return view('mails.base');
    }
}

Finally, the component should be registered with a service provider:

Blade::component('mails.base', \App\Views\Components\Base::class);

Now we can use the Blade-component like <x-mails.blade>. Finally, update the initial view file you created to fit inside the Blade-component:

<x-mails.base :subject="$subject">
    <!-- Your e-mail content -->
</x-mails.base>

You’re almost there. To summarize, we created a Blade layout component for the default HTML-markup in our emails, a mail.css file containing our Tailwind CSS classes, and a Blade-file containing our regular Laravel e-mail template.

 Inline Laravel e-mail CSS with the CSS inliner

The final step before this will work is to inline the CSS. To do so, we’ll need a Laravel-package via Composer that handles inlining the CSS into the emails automatically.

composer require fedeisas/laravel-mail-css-inliner
 
# If it complains about version constraints:
composer require "fedeisas/laravel-mail-css-inliner:dev-master"

Now, all the CSS in your e-mails will automatically be inlined from the stylesheet in the <head> of the page

As you can see, using Tailwind CSS for your Laravel e-mails is simple. It only takes a little setup and knowing the right tricks.

All the best nerd!

Leave a Reply