Emogrifier
Converts CSS styles into inline style attributes in your HTML code.
Install / Use
/learn @MyIntervals/EmogrifierREADME
Emogrifier
n. e•mog•ri•fi•er [\ē-'mä-grƏ-,fī-Ər] - a utility for changing completely the nature or appearance of HTML email, esp. in a particularly fantastic or bizarre manner
Emogrifier converts CSS styles into inline style attributes in your HTML code. This ensures proper display on email and mobile device readers that lack stylesheet support.
This utility was developed as part of Intervals to deal with the problems posed by certain email clients (namely Outlook 2007 and GoogleMail) when it comes to the way they handle styling contained in HTML emails. As many web developers and designers already know, certain email clients are notorious for their lack of CSS support. While attempts are being made to develop common email standards, implementation is still a ways off.
The primary problem with uncooperative email clients is that most tend to only
regard inline CSS, discarding all <style> elements and links to stylesheets
in <link> elements. Emogrifier solves this problem by converting CSS styles
into inline style attributes in your HTML code.
- How it works
- Installation
- Usage
- Supported CSS selectors
- Caveats
- Contributing
- Steps to release a new version
- Maintainers
How it Works
Emogrifier automagically transmogrifies your HTML by parsing your CSS and inserting your CSS definitions into tags within your HTML based on your CSS selectors.
Installation
For installing emogrifier, either add pelago/emogrifier to the require
section in your project's composer.json, or you can use composer as below:
composer require pelago/emogrifier
See https://getcomposer.org/ for more information and documentation.
Usage
Inlining Css
The most basic way to use the CssInliner class is to create an instance with
the original HTML, inline the external CSS, and then get back the resulting
HTML:
use Pelago\Emogrifier\CssInliner;
…
$visualHtml = CssInliner::fromHtml($html)->inlineCss($css)->render();
If there is no external CSS file and all CSS is located within <style>
elements in the HTML, you can omit the $css parameter:
$visualHtml = CssInliner::fromHtml($html)->inlineCss()->render();
If you would like to get back only the content of the <body> element instead
of the complete HTML document, you can use the renderBodyContent method
instead:
$bodyContent = $visualHtml = CssInliner::fromHtml($html)->inlineCss()
->renderBodyContent();
If you would like to modify the inlining process with any of the available options, you will need to call the corresponding methods before inlining the CSS. The code then would look like this:
$visualHtml = CssInliner::fromHtml($html)->disableStyleBlocksParsing()
->inlineCss($css)->render();
There are also some other HTML-processing classes available
(all of which are subclasses of AbstractHtmlProcessor) which you can use
to further change the HTML after inlining the CSS.
(For more details on the classes, please have a look at the sections below.)
CssInliner and all HTML-processing classes can share the same DOMDocument
instance to work on:
use Pelago\Emogrifier\CssInliner;
use Pelago\Emogrifier\HtmlProcessor\CssToAttributeConverter;
use Pelago\Emogrifier\HtmlProcessor\HtmlPruner;
…
$cssInliner = CssInliner::fromHtml($html)->inlineCss($css);
$domDocument = $cssInliner->getDomDocument();
HtmlPruner::fromDomDocument($domDocument)->removeElementsWithDisplayNone()
->removeRedundantClassesAfterCssInlined($cssInliner);
$finalHtml = CssToAttributeConverter::fromDomDocument($domDocument)
->convertCssToVisualAttributes()->render();
Normalizing and cleaning up HTML
The HtmlNormalizer class normalizes the given HTML in the following ways:
- add a document type (HTML5) if missing
- disentangle incorrectly nested tags
- add HEAD and BODY elements (if they are missing)
The class can be used like this:
use Pelago\Emogrifier\HtmlProcessor\HtmlNormalizer;
…
$cleanHtml = HtmlNormalizer::fromHtml($rawHtml)->render();
Converting CSS styles to visual HTML attributes
The CssToAttributeConverter converts a few style attributes values to visual
HTML attributes. This allows to get at least a bit of visual styling for email
clients that do not support CSS well. For example, style="width: 100px"
will be converted to width="100".
The class can be used like this:
use Pelago\Emogrifier\HtmlProcessor\CssToAttributeConverter;
…
$visualHtml = CssToAttributeConverter::fromHtml($rawHtml)
->convertCssToVisualAttributes()->render();
You can also have the CssToAttributeConverter work on a DOMDocument:
$visualHtml = CssToAttributeConverter::fromDomDocument($domDocument)
->convertCssToVisualAttributes()->render();
Evaluating CSS custom properties (variables)
The CssVariableEvaluator class can be used to apply the values of CSS
variables defined in inline style attributes to inline style properties which
use them.
For example, the following CSS defines and uses a custom property:
:root {
--text-color: green;
}
p {
color: var(--text-color);
}
After CssInliner has inlined that CSS on the (contrived) HTML
<html><body><p></p></body></html>, it will look like this:
<html style="--text-color: green;">
<body>
<p style="color: var(--text-color);">
<p>
</body>
</html>
The CssVariableEvaluator method evaluateVariables will apply the value of
--text-color so that the paragraph style attribute becomes color: green;.
It can be used like this:
use Pelago\Emogrifier\HtmlProcessor\CssVariableEvaluator;
…
$evaluatedHtml = CssVariableEvaluator::fromHtml($html)
->evaluateVariables()->render();
You can also have the CssVariableEvaluator work on a DOMDocument:
$evaluatedHtml = CssVariableEvaluator::fromDomDocument($domDocument)
->evaluateVariables()->render();
Removing redundant content and attributes from the HTML
The HtmlPruner class can reduce the size of the HTML by removing elements with
a display: none style declaration, and/or removing classes from class
attributes that are not required.
It can be used like this:
use Pelago\Emogrifier\HtmlProcessor\HtmlPruner;
…
$prunedHtml = HtmlPruner::fromHtml($html)->removeElementsWithDisplayNone()
->removeRedundantClasses($classesToKeep)->render();
The removeRedundantClasses method accepts an allowlist of names of classes
that should be retained. If this is a post-processing step after inlining CSS,
you can alternatively use removeRedundantClassesAfterCssInlined, passing it
the CssInliner instance that has inlined the CSS (and having the HtmlPruner
work on the DOMDocument). This will use information from the CssInliner to
determine which classes are still required (namely, those used in uninlinable
rules that have been copied to a <style> element):
$prunedHtml = HtmlPruner::fromDomDocument($cssInliner->getDomDocument())
->removeElementsWithDisplayNone()
->removeRedundantClassesAfterCssInlined($cssInliner)->render();
The removeElementsWithDisplayNone method will not remove any elements which
have the class -emogrifier-keep. So if, for example, there are elements which
by default have display: none but are revealed by an @media rule, or which
are intended as a preheader, you can add that class to those elements. The
paragraph in this HTML snippet will not be removed even though it has
display: none (which has presumably been applied by CssInliner::inlineCss()
from a CSS rule .preheader { display: none; }):
<p class="preheader -emogrifier-keep" style="display: none;">
Hello World!
</p>
The removeRedundantClassesAfterCssInlined (or removeRedundantClasses)
method, if invoked after removeElementsWithDisplayNone, will remove the
-emogrifier-keep class.
Options
There are several options that you can set on the CssInliner instance before
calling the inlineCss method:
->disableStyleBlocksParsing()- By default,CssInlinerwill grab all<style>blocks in the HTML and will apply the CSS styles as inline "style" attributes to the HTML. The<style>blocks will then be removed from the HTML. If you want to disable this functionality so thatCssInlinerleaves these<style>blocks in the HTML and does not parse them, you should use this option. If you use this option, the contents of the<style>blocks will not be applied as inline styles and any CSS you wantCssInlinerto use must be passed in as described in the Usage section above.->disableInlineStyleAttributesParsing()- By default,CssInlinerpreserves all of the "style" attributes on tags in the HTML you pass to it. However if you want to discard all existing inline styles in the HTML before the CSS is applied, you should use this option.->addAllowedMediaType(string $mediaName)- By default,CssInlinerwill keep only media typesall,screenand `p
Related Skills
node-connect
342.0kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
frontend-design
84.7kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
openai-whisper-api
342.0kTranscribe audio via OpenAI Audio Transcriptions API (Whisper).
commit-push-pr
84.7kCommit, push, and open a PR
