White labelling is the business practise of making aspects of your application styled to how your clients want it to look. In most cases of a web application serving many clients will want some form of customising of logos and company colours on pages.
In one instance recently though I had to build a way of adding this customisation, not to the frontend of the application but to the email templates. Not only did I need to add different logos which was a fairly simple task but I also needed to add different colours to certain sections of text as well as change the colour of buttons. There was a couple was ways of doing this but these would likely be quite difficult to work with long term. To begin with coming to my solution I just want to quickly explain how markdown emails work in Laravel and what sets the styles delivered in the final HTML.
How markdown emails work is essentially the HTML is generated from a mix of Blade templates with HTML and Markdown that gets converted to HTML. Once that is done the Laravel framework uses what it refers to as a theme, the default is a CSS file. It then begins a process that is called CSS Inlining. This is done because HTML Emails cannot use CSS refer links. Instead the styles defined in the theme CSS are converted to style attributes and assigned to the classes applied in the HTML nodes.
To cut a long story short, this:
Would then become this:
The problem is it’s not clear what you can and can’t do with the theme. It looks like it’s just a static CSS file that has to be selected for the notification, the documentation for this is actually pretty brief. This is a bit of problem if you have your styles set in a database etc.
There is a fairly simple solution though. In actual fact, if you dive into the code for Laravel you’ll find that you can use a Blade file instead of a CSS one and the Blade file will still receive all the parameters your Markdown template would. We can actually leverage this into applying minor tweaks to our CSS that will be used for HTML inlining.
So I’ve explained the how notifications are styled, I’ll quickly show you how you can take advantage of this to make dynamic emails based on who you’re delivering to.
The first step is to create the blade theme file. I’m just going to copy the original one (For Laravel 7 at least) which you can find in this gist I made. Then we’re going to add our theme to resources/views/vendors/mail/html/themes/whitelabel.blade.php which will contain all the CSS. The folders don’t exist by default so you’ll need to add them.
Then we need to change a simple section in our whitelabel.blade.php file so that in the event of a custom button attribute, the colour for the button is applied and if the custom style isn’t there you can just use the default.
What I’ve done now is set up a process that changes the default primary button in the CSS to use a bespoke colour when the custom styles parameter is present.
What we need now it to customise the mail message to enact this change in a relatively clean manner. I’ll first create an extending class of the MailMessage class used in notifications to instead provide a method which can set this button colour.
So then if we make a Notification we can replace the MailMessage returned in the toMail method with a CustomMailMessage that can accept our argument.
This way we can override the colour of the button in our markdown emails. Such as I set up a simple little route in my app to display these changes via a parameter in a url. Obviously you will likely want to build on this and actually determine the colours or provide other CSS styles based on the User you’re sending the notification to. Just so you can get an idea of how this turns out as an end result I’ve provided some screenshots below.
The original notification email:
The email with a color applied via the dynamic theme:
This is not a fool proof way of doing it. You will likely run into problems if you need to make drastic changes per client that wants emails styles a particular way but if you want to produce something simple very quickly and don’t mind mixing your blade and CSS this is a pretty effective technique compared to building components that apply special classes to HTML elements which can become equally as unmanageable. My suggest is that if you do need more you should consider looking at extending the \Illuminate\Mail\Markdown class to handle your dynamic needs.
If you’d like to view the code for this demo you can access it on GitHub.
I’m Peter Fox, a software developer in the UK who works with Laravel among other things. If you want to know more about me you can at https://www.peterfox.me and feel free to follow me @SlyFireFox on twitter for more Laravel tips and tutorials in the future.