Releases: maizzle/maizzle-php
v1.3.1
v1.3.0
v1.2.2
v1.2.1
v1.2.0
This release updates Tailwind CSS, fixes a few bugs and adds support for using hover-
utilities without a @media
query.
- Pseudo selectors now preserved
- Fixed
googleFonts
key format - Font family reset removed
lang=""
for webmail- Tailwind CSS 0.6.6
Pseudo selectors now preserved
Until now, you couldn't have used a utility like hover-text-green
, because Juice would have removed the CSS selector as part of the removeStyleTags
feature. The common solution was to 'hide' the selector inside a @media
query, so Juice would leave it alone - i.e. all-hover-text-green
.
This release updates Juice to version 5.0.0
, which fixes the inconvenience.
Fixed googleFonts
key format
Due to a recently introduced type check for the googleFonts
Front Matter variable, using a simple string was not working anymore. Updated the example templates and docs to use an array.
Font family reset removed
<td>
and <th>
were being reset to use the font-sans
utility class. This meant that, if you wanted to use a different font family on an element, you needed to override this reset either globally, or by adding a font-...
utility on every table cell.
This release removes the global font family reset, and adds it on the wrapper table instead.
lang=""
for webmail
Webmail clients, such as Gmail, completely remove your <html>
and <body>
tags. Since the lang=""
attribute is being set on the <html>
tag, this resulted in a situation where a screenreader could not use the language we specified, for correct pronunciation.
This release adds the lang=""
attribute on elements in the included templates, too. When creating a new template, it is highly advisable that you add this, just like in the examples.
Tailwind CSS 0.6.6
Updated to Tailwind CSS 0.6.6
, which fixes an issue where units were stripped from zero value properties, and promotes shadowLookup
from experiment to official feature.
There is also a borderCollapse: [],
module in the Tailwind config, which you can use if you ever need variants for border-collapse
on tables.
v1.1.3
#outlook a
removed
Testing in Outlook 2013/2016 shows that #outlook a {padding: 0;}
isn't needed for the 'view in browser' bar to show up, so it has been removed.
Custom MSO styles per template
outlook-conditional.blade.php
now checks if there's a Blade section named mso-css
in your template. If it finds it (and it's not empty), it will use its contents in the <style>
tag from the <!--[if mso]>
conditional in a layout's <head>
.
For example, say we wanted a different font stack for this email instead of the default one (that is using Segoe UI), as well as some extra MSO-specific table styling:
// custom-mso-css.blade.md
---
title: Custom MSO styling example
---
@section('mso-css')
table {border-collapse: collapse; mso-table-lspace: 0pt; mso-table-rspace: 0pt;}
td,th,div,p,a,h1,h2,h3,h4,h5,h6 {font-family: Helvetica, Arial, sans-serif; mso-line-height-rule: exactly;}
@endsection
<table ...
Note: whatever you have in this section will replace the default CSS for Outlook that Maizzle comes with.
v1.1.2
v1.1.1
Improved CSS class cleanup
Maizzle now exposes email-remove-unused-css
's backend
option in your config, which you can use to define heads/tails pairs of characters that wrap your CSS class names, so the cleanup library doesn't remove those classes.
A {{
}}
pair is included - useful if you're using Blade to further process an email after Maizzle compiles it:
'cleanup' => [
'removeUnusedCss' => [
// ...
'backend' => [
[
'heads' => "{{",
'tails' => "}}",
],
],
// ...
],
],
Imagine foo = 'odd'
somewhere in your application. Previously, if you wanted to output Blade from Maizzle:
<tr class="@{{ foo }}">
... you would have ended up with this in the compiled HTML:
<!-- foo is removed 😩 -->
<tr class="{{ }}">
Having {{
and }}
defined as heads/tails in the backend
option, the compiled HTML will now look like this:
<!-- we can now use `foo` 👌 -->
<tr class="{{ foo }}">
Don't load extraBorderUtilities
plugin by default
The require
for this Tailwind CSS plugin is now commented out by default, as it's not really needed in most cases. Simply uncomment this line in tailwind.js
, if you need it:
// require('./tailwind/plugins/extraBorderUtilities'),
v1.1.0
This release adds some cool new features, and fixes some minor issues.
Specifically, it:
- Switches from Sass to PostCSS
- Now generates plaintext versions
- Can rewrite CSS to shorthand
- Adds a doctype option
- Introduces Blade Stacks
- Exposes more of Juice's options
- Drops
removeStyleTags
from the configs - Adds a new
@env
Blade directive - Adds custom Tailwind utilities
- Adds Tailwind plugins for borders and background gradients
- Adds other, miscellaneous updates
Switch to PostCSS
Maizzle now uses PostCSS instead of Sass.
It's faster, avoids preprocessor gotchas (like a Python dependency for node-sass
in Windows, or not being able to use Tailwind's @apply
with !important
), and makes more sense considering the tooling being used.
Plaintext Versions
Maizzle can now automatically generate plaintext versions of your emails, with the help of string-strip-html.
A new 'plaintext' => false,
option has been added to the configs. When you set it to true
, Maizzle will generate a plaintext version for every template. The .txt
file will be placed in the same directory as the HTML it's based on, and it will also have the same name.
Plaintext is enabled by default for production builds, in config.production.php
.
Shortand CSS
Maizzle now uses postcss-merge-longhand to rewrite your CSS padding
, margin
, and border
in shorthand-form, where possible. Because Tailwind classes mostly map one-to-one with CSS properties, this won't have any effect on them. Instead, it's very useful when you extract components with Tailwind's @apply
.
For example, considering this template:
---
title: Confirm your email
preheader: Please verify your email address with us
bodyClasses: bg-grey-light
---
<div class="col">test</div>
... let's extract a .col
class in an imaginary source/_styles/components.css
:
.col {
@apply py-8 px-4;
}
Previously, that would have given us this:
<div style="padding-top: 8px; padding-bottom: 8px; padding-left: 4px; padding-right: 4px;">test</div>
Now, thanks to postcss-merge-longhand
, we get this:
<div style="padding: 8px 4px;">test</div>
As mentioned, this works for padding
, margin
, and border
. Using shorthand CSS for these is well supported in email clients and will make your HTML lighter, but the shorthand border is particularly useful because it's the only way Outlook will render it properly.
Note: the library won't assume any missing values. For padding and margin, the class needs to specify properties for all four sides. For borders, see the example below.
Shorthand borders
To get the PostCSS plugin to rewrite your CSS borders in shorthand-form, you need to specify all these:
- border-width
- border-style
- border-color
When extracting a component class in Tailwind, that means you can do something like this:
.my-border {
@apply border border-solid border-blue;
}
... which, following the example above, will result in this shorthand form:
<div style="border: 1px solid #3490dc;">test</div>
DOCTYPE option
You can now set a doctype for your emails, either globally or per-template.
There is a new doctype
option in config.php
:
'doctype' => 'html',
This is used in the default layout(s) that Maizzle comes with:
<!DOCTYPE {!! $page->doctype ?? 'html' !!}>
Note: the {!! !!}
Blade statement is used instead of {{ }}
. This is to prevent the value from being escaped - helps if you use an older doctype, like in the front matter example below.
The global variable set in config.php
can be overridden at a template level, just like any other option:
---
doctype: html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
title: Confirm your email
preheader: Please verify your email address with us
---
Stacks
Maizzle's default layouts now include a @stack('head')
directive (see Blade docs).
This allows you to use @push('head')
and @prepend('head')
in your Blade email files, to add anything you'd like right before the closing </head>
tag.
You could use this to add custom <style>
blocks on a per-template basis. Email client-specific CSS resets make for a good example:
source/emails/confirm-email.blade.md
---
// front matter needs to be first!
---
@push('head')
<style data-embed>
a[x-apple-data-detectors] {color: inherit; text-decoration: none;}
</style>
@endpush
<table ...
You can push multiple stacks, too:
---
...
---
@push('head')
<style data-embed>
a[x-apple-data-detectors] {color: inherit; text-decoration: none;}
</style>
@endpush
@push('head')
<meta name="format-detection" content="telephone=no">
<meta name="format-detection" content="date=no">
<meta name="format-detection" content="address=no">
<meta name="format-detection" content="email=no">
@endpush
Of course, you can use it for anything you'd like to have right before </head>
, for this template only: additional meta tags, Outlook conditionals, custom ESP code - you name it!
Notes:
-
When
@push
ing a<style>
, you need to add adata-embed
attribute on it, so that the inliner leaves it alone. -
You cannot use Tailwind CSS
@
-rules here. Tailwind is processed before this file is, so using something like@apply
will have no effect.
More Juice options
styleToAttribute
Maizzle now exposes juice.styleToAttribute
to your configs, so you can define which CSS properties should be also added as HTML attributes to table elements that Juice knows about.
This is opt-out by design, and will only have effect if inlining is enabled.
You can customise the styleToAttribute
key under inlineCSS
, mapping CSS properties to HTML attributes.
For example this:
// config.production.php
'transformers' => [
'inlineCSS' => [
'enabled' => true,
'styleToAttribute' => [
'background-color' => 'bgcolor',
],
],
...
],
... will transform this:
<!-- using Tailwind class here... -->
<table class="bg-white">
...
</table>
... to this:
<table style="background-color: #ffffff;" bgcolor="#ffffff">
...
</table>
Opt-out by design
By default, Maizzle configs include the styleToAttribute
key, and populate it with Juice's defaults.
This is on purpose, for better email client compatibility.
However, if you specify a single mapping, like we did in the example above, Juice will only convert that to an attribute, keeping any other property as inline CSS-only.
codeBlocks
Maizzle now exposes juice.codeBlocks
to your config, so that you can define additional fenced code blocks that you need Juice to ignore when inlining.
codeBlocks
must be an array of items matching juice.codeBlocks
dictionary format.
For example:
// config.production.php
'inlineCSS' => [
'enabled' => true,
'codeBlocks' => [
'ASP' => ['start' => '<%@', 'end' => '%>'],
],
],
The above will add the ASP
key to Juice's juice.codeBlocks
dictionary, so that Juice doesn't treat something like <%@ page language="C#" %>
as an HTML tag that needs to have CSS inlined.
applySizeAttribute
There is a new applySizeAttribute
key under the inlineCSS
options:
'inlineCSS' => [
'enabled' => true,
// ...
'applySizeAttribute' => [
'width' => ['TABLE', 'TD', 'TH', 'IMG', 'VIDEO'],
'height' => ['TABLE', 'TD', 'TH', 'IMG', 'VIDEO'],
],
],
Under the width
and height
keys, you can specify an array of elements that should receive width=""
and height=""
attributes. These elements will be passed to the Juice inliner, which will duplicate any inline width and height CSS rules it finds as HTML attributes, but only for those elements.
excludedProperties
The new excludedProperties
option allows you to define an array of CSS properties that should be excluded from the CSS inlining process by Juice:
'inlineCSS' => [
'enabled' => true,
// ...
'excludedProperties' => [],
],
Maizzle sets this as an empty array in the production environment configs.
Property names are considered unique, so you need to specify each one you'd like to exclude. For example:
'excludedProperties' => ['padding', 'padding-left'],
Note: corresponding classes that they're derived from (i.e. pl-2
) will still be removed from your HTML if removeUnusedCss
is enabled. To prevent this, you could add 'removeStyleTags' => false,
in the inlineCSS
options array.
removeStyleTags
removeStyleTags
has been...
v1.0.2
This release exposes new CSS cleanup options in config.php, thanks to v4.2.0
of email-remove-unused-css
.
You now have two new options in removeUnusedCss
:
1. removeHTMLComments
'enabled' => true,
will remove any HTML comments in your compiled email. Set to false
to not remove any comments.
preserve
can be set to an array of strings. If any comment's opening tag contains any of these strings, that comment will not be removed.
Warning: if using removeHTMLComments
but want to preserve certain comments such as Outlook conditionals, you need to explicit about both the starting and ending comment in the preserve
strings, because they are treated as two separate comments.
Basically, don't do this:
// will remove your closing <![endif]--> comment
'preserve' => ['if', 'mso', 'ie'],
Instead, do this:
// will preserve Outlook conditional comments as expected
'preserve' => ['if', 'endif', 'mso', 'ie'],
Maizzle defaults to the email-remove-unused-css
library defaults (['if', 'endif', 'mso', 'ie']
) both in the config.*.php
, and as a fallback: if you enable removeHTMLComments
but don't specify a list of strings (or specify an empty array for preserve
), it will still properly handle Outlook conditionals.
2. uglify
This is a very cool option introduced in email-remove-unused-css v4.2.0
: it renames all your classes, in both HTML and CSS, to be very short (starting from a single character). It's a small but very useful feature, especially for complex layouts where you need to shave off as many KB as possible to avoid Gmail clipping.
For example, this:
<style>
.text-purple-lightest {color: #f3ebff;}
.bg-grey-darkest {color: #3d4852;}
</style>
<table>
<tr>
<td class="bg-grey-darkest">
<p class="text-purple-lightest">Lorem ipsum</p>
</td>
</tr>
</table>
gets transformed to something like this:
<style>
.a {color: #f3ebff;}
.b {color: #3d4852;}
</style>
<table>
<tr>
<td class="b">
<p class="a">Lorem ipsum</p>
</td>
</tr>
</table>
Maizzle enables uglify
by default only in config.production.php
.