CSS configuration
Configuring Tailwind CSS and how CSS is compiled in Maizzle.
Options
CSS handling in Maizzle can be configured under the css
key in your config.js
file:
export default {
css: {
inline: true,
purge: true,
resolveCalc: true,
resolveProps: true,
safe: true,
shorthand: true,
sixHex: true,
tailwind: {},
},
}
inline
Type: Boolean
Default: undefined
Configure how CSS is inlined in your HTML emails.
For details, see the CSS inlining documentation.
purge
Type: Boolean|Object
Default: undefined
Configure email-safe unused CSS purging.
For details, see the CSS Purge Transformer docs.
resolveCalc
Type: Boolean|PostCssCalcOptions
Default: true
Whether to resolve calc()
expressions in the CSS to their computed values.
By default, something like this:
<style>
div {
width: calc(100% / 3);
}
</style>
... will be compiled to:
<style>
div {
width: 33.33%;
}
</style>
calc()
expressions.
This uses postcss-calc
to resolve calc()
functions in your CSS to their computed values whenever possible. When multiple units are mixed in the same calc()
expression, the statement will be output as-is.
You may pass an object to configure postcss-calc
:
export default {
css: {
resolveCalc: {
precision: 3, // precision for decimal numbers (2 by default)
},
},
}
See the postcss-calc options.
resolveProps
Type: Boolean|Object
Default: true
CSS custom properties, or CSS variables, are poorly supported in email clients. Whenever you use them, Maizzle will try to resolve them to their static representation.
You may configure this behavior by setting the resolveProps
key to false
(to disable it) or to a postcss-css-variables
options object:
export default {
css: {
resolveProps: false, // or postcss-css-variables options
},
}
See the postcss-css-variables options.
safe
Type: Boolean|Object
Default: true
Rewrites Tailwind CSS class names to email-safe alternatives.
See the Safe Class Names Transformer docs.
shorthand
Type: Boolean|Object
Default: undefined
Configure rewriting of CSS properties to their shorthand form. Disabled by default.
See the Shorthand Transformer docs.
sixHex
Type: Boolean
Default: true
Whether to convert 3-digit HEX colors to 6-digit HEX colors. Enabled by default.
See the Six HEX Transformer docs.
tailwind
You'll probably only need this when using Maizzle programmatically - otherwise you can use the @config
directive in your CSS to specify a custom Tailwind CSS config file to use.
It's important to note that when using css.tailwind
you need to provide a Tailwind CSS configuration object with all values that you need to be different from Tailwind's defaults. So you need to specify px
values, screens etc. that work in email clients:
export default {
css: {
tailwind: {
content: [
'./components/**/*.html',
'./emails/**/*.html',
'./layouts/**/*.html',
],
important: true,
screens: {
sm: {max: '600px'},
xs: {max: '425px'},
},
spacing: {
px: '1px',
0.5: '2px',// etc.
},
},
},
}
If you want, you can import tailwindcss-preset-email
:
import emailPreset from 'tailwindcss-preset-email'
export default {
css: {
tailwind: {
presets: [ emailPreset ],
content: [ /* ... */ ],
},
},
}
tailwind.config.js
Maizzle uses tailwindcss-preset-email
, a custom preset that configures Tailwind CSS for better email client support.
This preset helps generate more email-friendly CSS, by disabling some of the default Tailwind CSS features that are not well supported in email clients.
For example, HEX values are preferred over CSS variables, and rem
units are replaced with px
units.
content
By default, Tailwind CSS in Maizzle is configured to scan all .html
files in your project's src
directory for classes to generate:
export default {
content: [
'./components/**/*.html',
'./emails/**/*.html',
'./layouts/**/*.html',
],
}
!important
HTML emails still need to use inline CSS, most notably for these reasons:
- Outlook/Office 365 for Windows only reads the first class in a
class=""
attribute, ignoring the rest. So it'll only usea
fromclass="a b"
- Some email clients don't support embedded CSS (i.e. in
<style>
) - Embedded styles are often discarded when an email is forwarded
The Tailwind preset in Maizzle sets important: true
- this way, things like responsive utilities can actually override inline CSS.
<style>
tags will use
!important
, inlined CSS in
style=""
attributes will not.
You may disable this behavior by setting the important
key to false
:
/** @type {import('tailwindcss').Config} */
module.exports = {
presets: [
require('tailwindcss-preset-email'),
],
important: false,
}
separator
Characters like :
in hover:bg-black
need to be \escaped in CSS.
Because some email clients (Gmail 👀) fail to parse selectors with escaped characters, Maizzle normalizes all your CSS selectors and HTML classes, replacing any escaped characters it finds with email-safe alternatives.
So you can safely use Tailwind's awesome default separator and write classes like sm:w-1/2
- Maizzle will convert that to sm-w-1-2
in your compiled template.
You may also configure the replacement mappings if you need to.
screens
Maizzle uses a desktop-first approach with max-width
media queries instead of Tailwind's default, mobile-first approach that uses min-width
.
These are the default screens in Maizzle:
export default {
screens: {
sm: {max: '600px'},
xs: {max: '425px'},
},
}
Of course, you're free to adjust this as you like. For example, you might add a breakpoint that targets tablet devices based on their viewport width:
/** @type {import('tailwindcss').Config} */
module.exports = {
presets: [
require('tailwindcss-preset-email'),
],
screens: {
md: {min: '768px', max: '1023px'},
sm: {max: '600px'},
xs: {max: '425px'},
},
}
That would enable you to write classes like md:hidden
or md:text-lg
, which will be wrapped in a @media (min-width: 768px) and (max-width: 1023px)
media query.
More on screens, in the Tailwind CSS docs.
colors
Maizzle uses the default color palette from Tailwind CSS.
You may define your own colors, or even extend or change the default color palette by adding a colors
key to your Tailwind config:
import emailPreset from 'tailwindcss-preset-email'
/** @type {import('tailwindcss').Config} */
export default {
presets: [
emailPreset,
],
theme: {
extend: {
colors: {
blue: {
// change 'blue-500'
500: '#03a9f4',
// add 'blue-1000'
1000: '#101e47',
},
// custom color
primary: '#FFCC00',
}
}
}
}
spacing
The spacing scale has been extended to include more values:
spacing: {
screen: '100vw',
full: '100%',
px: '1px',
0: '0',
0.5: '2px',
1: '4px',
// ...
14: '56px',
16: '64px',
18: '72px',
// ...
48: '192px',
50: '200px',
// ...
96: '384px',
},
borderRadius
borderRadius: {
none: '0px',
sm: '2px',
DEFAULT: '4px',
md: '6px',
lg: '8px',
xl: '12px',
'2xl': '16px',
'3xl': '24px',
},
boxShadow
The tailwindcss-box-shadow plugin is used to output box-shadow
CSS values exactly as you have them defined in your Tailwind CSS config.
boxShadow: {
sm: '0 1px 2px 0 rgba(0, 0, 0, 0.05)',
DEFAULT: '0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px -1px rgba(0, 0, 0, 0.1)',
md: '0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -2px rgba(0, 0, 0, 0.1)',
lg: '0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -4px rgba(0, 0, 0, 0.1)',
xl: '0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 8px 10px -6px rgba(0, 0, 0, 0.1)',
'2xl': '0 25px 50px -12px rgba(0, 0, 0, 0.25)',
inner: 'inset 0 2px 4px 0 rgba(0, 0, 0, 0.05)',
},
fontFamily
Font stacks are the default ones from Tailwind CSS, but simplified. We also include a stack for the Inter font:
fontFamily: {
inter: ['Inter', 'ui-sans-serif', 'system-ui', '-apple-system', '"Segoe UI"', 'sans-serif'],
sans: ['ui-sans-serif', 'system-ui', '-apple-system', '"Segoe UI"', 'sans-serif'],
serif: ['ui-serif', 'Georgia', 'Cambria', '"Times New Roman"', 'Times', 'serif'],
mono: ['ui-monospace', 'Menlo', 'Consolas', 'monospace'],
},
fontSize
Pixel values are preferred for font size utilities:
fontSize: {
0: '0',
xxs: '11px',
xs: '12px',
'2xs': '13px',
sm: '14px',
'2sm': '15px',
base: '16px',
lg: '18px',
xl: '20px',
'2xl': '24px',
'3xl': '30px',
'4xl': '36px',
'5xl': '48px',
'6xl': '60px',
'7xl': '72px',
'8xl': '96px',
'9xl': '128px',
},
lineHeight
The lineHeight
utilities have been extended to include all spacing
scale values:
lineHeight: theme => ({
...theme('spacing'),
}),
So you can use leading
utilities to easily create vertical spacing, like this:
<div class="leading-16">‍</div>
Result:
<div style="line-height: 64px">‍</div>
maxWidth
maxWidth: theme => ({
...theme('spacing'),
xs: '160px',
sm: '192px',
md: '224px',
lg: '256px',
xl: '288px',
'2xl': '336px',
'3xl': '384px',
'4xl': '448px',
'5xl': '512px',
'6xl': '576px',
'7xl': '640px',
}),
Pixel units
Because of poor email client support, our email preset for Tailwind CSS replaces rem
units with px
.
This affects the following utilities:
spacing
(width, height, margin, padding, etc)maxWidth
borderRadius
fontSize
lineHeight
Plugins
You can of course use any Tailwind CSS plugin, all you have to do is to install it from NPM and then import
or require
it in your tailwind.config.js
.
npm install tailwindcss-email-variants
With import
:
import emailVariants from 'tailwindcss-email-variants'
export default {
plugins: [
emailVariants,
],
}
With require
:
module.exports = {
plugins: [
require('tailwindcss-email-variants'),
],
}
tailwindcss-email-variants
is already included in the email preset, no need to install it.
Disabled plugins
tailwindcss-preset-email
disables the following Tailwind CSS core plugins due to poor support in the majority of email clients:
- preflight
- backgroundOpacity
- borderOpacity
- borderSpacing
- divideOpacity
- placeholderOpacity
- textOpacity
- textDecoration
If you want to use one of these plugins, simply set it to true
in corePlugins
at the bottom of your tailwind.config.js
:
corePlugins: {
backgroundOpacity: false,
backgroundOpacity: true,
}