Automatic CSS Inlining

Keep on Learning!

If you liked what you've learned so far, dive in!
Subscribe to get access to this tutorial plus
video, code and script downloads.

Start your All-Access Pass
Buy just this tutorial for $12.00

With a Subscription, click any sentence in the script to jump to that part of the video!

Login Subscribe

Our email looks good in Mailtrap, but will it look good in Gmail or Outlook? That's one of the things that Mailtrap can't answer: it gives us a ton of great info about our email... but it is not showing an accurate representation of how it would look in the real world. If you need to be super strict about making sure your email looks good everywhere, check out services like Litmus.

But generally speaking, there are two big rules you should follow if you want your emails to display consistently across all mail clients. First, use a table-based layout instead of floating or Flex-box. We'll talk about how to do this... without hating it... a bit later. The second rule is that you can't use CSS files or even add a <style> tag. These will not work in gmail. If you want to style your elements... which you totally do... then you literally need to add style="" to every HTML element.

But... that's insane! It's no way to live! So... we are not going to do that. Well... what I mean is, we are not going to do that manually.

Checking for the twig-pack

To get this all working, we need to check that a certain bundle is installed. If you started your project after October 2019, you can skip this because you will already have it.

For older projects, first make sure you have Twig 2.12 or higher: you can find your version by running:

composer show twig/twig

Mine is too old, so I'll update it by running:

composer update twig/twig

Now run:

composer require twig

That... might look confusing: don't we already have Twig installed? Before October 2019, composer require twig installed TwigBundle... only. But if you run this command after October 16th, 2019 - to be exact - the twig alias will download symfony/twig-pack. The only difference is that the twig-pack will install the normal TwigBundle and a new twig/extra-bundle, which is a library that will help us use some new Twig features. You'll see what I mean.

The main point is: make sure twig/extra-bundle is installed, and the best way to get it is from the pack. If you installed Twig after October 2019, you probably already have it.

The inline_css Filter

Ok, back to work! In welcome.html.twig, all the way on top, add {% apply inline_css %}.

inline_css is actually a filter... and in Twig, you normally use a filter with the | symbol - like foo|inline_css. But if you want to run a lot of stuff through a filter, you can do it with this handy apply tag. At the bottom of the template, say {% endapply %}.

{% apply inline_css %}
... lines 2 - 98
{% endapply %}

And... that's it! This passes our entire template through this filter... which is super smart. It reads the CSS from inside the style tag and uses that to add style attributes to every HTML element that it finds. Yea... it's crazy!

Let's see this in action. Go back to /register and fill the form back in... I'll use thetruthisoutthere9@example.com, any password, agree and... register!

TwigExtraBundle Invites you to Install Packages

It works! I'm kidding! But it's the next best thing. The error tells us exactly what's going on:

The "inline_css" filter is part of the CssInlinerExtension - try running "composer require twig/cssinliner-extra"

Why, what a fabulous idea! This error comes from that new TwigExtraBundle, which allows you to install several outside Twig extension libraries and start using them immediately with zero config. And... to be even shinier, if you try to use a feature but don't have the library that the feature requires, it tells you!

Copy the composer require line, move over to your terminal, and run:

composer require twig/cssinliner-extra

When that finishes... move over to the browser again, hit back and... let's change the email to 9b to be unique. Type a password, hit enter and... go check out that email! It still looks the same... but check out the HTML source. The style tag is still there but if you scroll... wow. The styles have been applied to every element!

This is one of my absolute favorite features of mailer. It's a huge chore that... just works.

Next, let's use this to clean things up even more. Instead of having all this CSS right in the template, let's use a proper, standalone CSS file.

Leave a comment!

This tutorial is built on Symfony 4.3, but will work well with Symfony 4.4 or 5.

What PHP libraries does this tutorial use?

// composer.json
{
    "require": {
        "php": "^7.1.3",
        "ext-iconv": "*",
        "aws/aws-sdk-php": "^3.87", // 3.110.11
        "knplabs/knp-markdown-bundle": "^1.7", // 1.7.1
        "knplabs/knp-paginator-bundle": "^2.7", // v2.8.0
        "knplabs/knp-snappy-bundle": "^1.6", // v1.6.0
        "knplabs/knp-time-bundle": "^1.8", // v1.9.1
        "league/flysystem-aws-s3-v3": "^1.0", // 1.0.23
        "league/flysystem-cached-adapter": "^1.0", // 1.0.9
        "league/html-to-markdown": "^4.8", // 4.8.2
        "liip/imagine-bundle": "^2.1", // 2.1.0
        "nexylan/slack-bundle": "^2.1,<2.2.0", // v2.1.0
        "oneup/flysystem-bundle": "^3.0", // 3.1.0
        "php-http/guzzle6-adapter": "^1.1", // v1.1.1
        "sensio/framework-extra-bundle": "^5.1", // v5.4.1
        "stof/doctrine-extensions-bundle": "^1.3", // v1.3.0
        "symfony/asset": "^4.0", // v4.3.4
        "symfony/console": "^4.0", // v4.3.4
        "symfony/flex": "^1.0", // v1.6.2
        "symfony/form": "^4.0", // v4.3.4
        "symfony/framework-bundle": "^4.0", // v4.3.4
        "symfony/mailer": "4.3.*", // v4.3.4
        "symfony/messenger": "4.3.*", // v4.3.4
        "symfony/orm-pack": "^1.0", // v1.0.6
        "symfony/security-bundle": "^4.0", // v4.3.4
        "symfony/sendgrid-mailer": "4.3.*", // v4.3.4
        "symfony/serializer-pack": "^1.0", // v1.0.2
        "symfony/twig-bundle": "^4.0", // v4.3.4
        "symfony/twig-pack": "^1.0", // v1.0.0
        "symfony/validator": "^4.0", // v4.3.4
        "symfony/web-server-bundle": "^4.0", // v4.3.4
        "symfony/webpack-encore-bundle": "^1.4", // v1.6.2
        "symfony/yaml": "^4.0", // v4.3.4
        "twig/cssinliner-extra": "^2.12", // v2.12.0
        "twig/extensions": "^1.5", // v1.5.4
        "twig/inky-extra": "^2.12" // v2.12.0
    },
    "require-dev": {
        "doctrine/doctrine-fixtures-bundle": "^3.0", // 3.2.2
        "easycorp/easy-log-handler": "^1.0.2", // v1.0.7
        "fzaninotto/faker": "^1.7", // v1.8.0
        "symfony/browser-kit": "4.3.*", // v4.3.5
        "symfony/debug-bundle": "^3.3|^4.0", // v4.3.4
        "symfony/dotenv": "^4.0", // v4.3.4
        "symfony/maker-bundle": "^1.0", // v1.13.0
        "symfony/monolog-bundle": "^3.0", // v3.4.0
        "symfony/phpunit-bridge": "^3.3|^4.0", // v4.3.4
        "symfony/profiler-pack": "^1.0", // v1.0.4
        "symfony/var-dumper": "^3.3|^4.0" // v4.3.4
    }
}