名词e•mog•ri•fi•er [ē-'mä-grƏ-,fī-Ər] - 用于完全更改 HTML 电子邮件(尤其是电子邮件)的性质或外观的实用程序。以一种特别奇妙或奇怪的方式
Emogrifier 将 CSS 样式转换为 HTML 代码中的内联样式属性。这可确保在缺乏样式表支持的电子邮件和移动设备阅读器上正确显示。
该实用程序是作为 Intervals 的一部分开发的,旨在解决某些电子邮件客户端(即 Outlook 2007 和 GoogleMail)在处理 HTML 电子邮件中包含的样式的方式时出现的问题。正如许多 Web 开发人员和设计师已经知道的那样,某些电子邮件客户端因缺乏 CSS 支持而臭名昭著。尽管人们正在尝试制定通用电子邮件标准,但实施仍有很长的路要走。
不合作的电子邮件客户端的主要问题是大多数倾向于只考虑内联 CSS,丢弃所有<style>
元素以及指向<link>
元素中样式表的链接。 Emogrifier 通过将 CSS 样式转换为 HTML 代码中的内联样式属性来解决此问题。
Emogrifier 通过解析您的 CSS 并根据您的 CSS 选择器将 CSS 定义插入到 HTML 内的标签中,自动改变您的 HTML。
要安装 emogrifier,请将pelago/emogrifier
添加到项目的composer.json
中的require
部分,或者您可以使用composer,如下所示:
composer require pelago/emogrifier
请参阅 https://getcomposer.org/ 了解更多信息和文档。
使用CssInliner
类的最基本方法是使用原始 HTML 创建一个实例,内联外部 CSS,然后返回生成的 HTML:
use Pelago Emogrifier CssInliner ;
…
$ visualHtml = CssInliner:: fromHtml ( $ html )-> inlineCss ( $ css )-> render ();
如果没有外部 CSS 文件并且所有 CSS 都位于 HTML 中的<style>
元素内,则可以省略$css
参数:
$ visualHtml = CssInliner:: fromHtml ( $ html )-> inlineCss ()-> render ();
如果您只想返回<body>
元素的内容而不是完整的 HTML 文档,您可以使用renderBodyContent
方法:
$ bodyContent = $ visualHtml = CssInliner:: fromHtml ( $ html )-> inlineCss ()
-> renderBodyContent ();
如果您想使用任何可用选项修改内联过程,则需要在内联 CSS 之前调用相应的方法。代码将如下所示:
$ visualHtml = CssInliner:: fromHtml ( $ html )-> disableStyleBlocksParsing ()
-> inlineCss ( $ css )-> render ();
还有一些其他可用的 HTML 处理类(所有这些类都是AbstractHtmlProcessor
的子类),您可以在内联 CSS 后使用它们进一步更改 HTML。 (有关这些类的更多详细信息,请查看以下部分。) CssInliner
和所有 HTML 处理类可以共享相同的DOMDocument
实例来处理:
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 ();
HtmlNormalizer
类通过以下方式标准化给定的 HTML:
该类可以这样使用:
use Pelago Emogrifier HtmlProcessor HtmlNormalizer ;
…
$ cleanHtml = HtmlNormalizer:: fromHtml ( $ rawHtml )-> render ();
CssToAttributeConverter
将一些样式属性值转换为可视 HTML 属性。这允许为不太支持 CSS 的电子邮件客户端至少获得一些视觉样式。例如, style="width: 100px"
将转换为width="100"
。
该类可以这样使用:
use Pelago Emogrifier HtmlProcessor CssToAttributeConverter ;
…
$ visualHtml = CssToAttributeConverter:: fromHtml ( $ rawHtml )
-> convertCssToVisualAttributes ()-> render ();
您还可以让CssToAttributeConverter
在DOMDocument
上工作:
$ visualHtml = CssToAttributeConverter:: fromDomDocument ( $ domDocument )
-> convertCssToVisualAttributes ()-> render ();
CssVariableEvaluator
类可用于将内联样式属性中定义的 CSS 变量的值应用到使用它们的内联样式属性。
例如,以下 CSS 定义并使用自定义属性:
: root {
--text-color : green;
}
p {
color : var ( --text-color );
}
CssInliner
在(设计的)HTML <html><body><p></p></body></html>
上内联该 CSS 后,它将如下所示:
< html style =" --text-color: green; " >
< body >
< p style =" color: var(--text-color); " >
< p >
</ body >
</ html >
CssVariableEvaluator
方法evaluateVariables
将应用--text-color
的值,使段落style
属性变为color: green;
。
它可以这样使用:
use Pelago Emogrifier HtmlProcessor CssVariableEvaluator ;
…
$ evaluatedHtml = CssVariableEvaluator:: fromHtml ( $ html )
-> evaluateVariables ()-> render ();
您还可以让CssVariableEvaluator
在DOMDocument
上工作:
$ evaluatedHtml = CssVariableEvaluator:: fromDomDocument ( $ domDocument )
-> evaluateVariables ()-> render ();
HtmlPruner
类可以通过删除具有display: none
样式声明的元素和/或从不需要的class
属性中删除类来减小 HTML 的大小。
它可以这样使用:
use Pelago Emogrifier HtmlProcessor HtmlPruner ;
…
$ prunedHtml = HtmlPruner:: fromHtml ( $ html )-> removeElementsWithDisplayNone ()
-> removeRedundantClasses ( $ classesToKeep )-> render ();
removeRedundantClasses
方法接受应保留的类名称白名单。如果这是内联 CSS 后的后处理步骤,您也可以使用removeRedundantClassesAfterCssInlined
,将其传递给已内联 CSS CssInliner
实例(并让HtmlPruner
在DOMDocument
上工作)。这将使用来自CssInliner
的信息来确定仍然需要哪些类(即,在已复制到<style>
元素的不可内联规则中使用的类):
$ prunedHtml = HtmlPruner:: fromDomDocument ( $ cssInliner -> getDomDocument ())
-> removeElementsWithDisplayNone ()
-> removeRedundantClassesAfterCssInlined ( $ cssInliner )-> render ();
removeElementsWithDisplayNone
方法不会删除任何具有类-emogrifier-keep
元素。因此,例如,如果某些元素默认具有display: none
但通过@media
规则显示,或者打算用作前置头,则可以将该类添加到这些元素中。此 HTML 代码段中的段落不会被删除,即使它具有display: none
(这可能是由CssInliner::inlineCss()
从 CSS 规则.preheader { display: none; }
应用的):
< p class =" preheader -emogrifier-keep " style =" display: none; " >
Hello World!
</ p >
如果在removeElementsWithDisplayNone
之后调用removeRedundantClassesAfterCssInlined
(或removeRedundantClasses
)方法,将删除-emogrifier-keep
类。
在调用inlineCss
方法之前,您可以在CssInliner
实例上设置几个选项:
->disableStyleBlocksParsing()
- 默认情况下, CssInliner
将抓取 HTML 中的所有<style>
块,并将 CSS 样式作为内联“样式”属性应用到 HTML。然后, <style>
块将从 HTML 中删除。如果您想禁用此功能,以便CssInliner
将这些<style>
块保留在 HTML 中并且不解析它们,您应该使用此选项。如果您使用此选项, <style>
块的内容将不会应用为内联样式,并且您希望CssInliner
使用的任何 CSS 都必须按照上面的“用法”部分中的描述传入。->disableInlineStyleAttributesParsing()
- 默认情况下, CssInliner
会保留传递给它的 HTML 中标记上的所有“样式”属性。但是,如果您想在应用 CSS 之前放弃 HTML 中所有现有的内联样式,则应该使用此选项。->addAllowedMediaType(string $mediaName)
- 默认情况下, CssInliner
将仅保留媒体类型all
、 screen
和print
。如果你想保留一些其他的,你可以使用这个方法来定义它们。->removeAllowedMediaType(string $mediaName)
- 您可以使用此方法删除 Emogrifier 保留的媒体类型。->addExcludedSelector(string $selector)
- 防止元素受到 CSS 内联的影响。请注意,只有与所提供的选择器匹配的元素才会被排除在 CSS 内联之外,而不一定是它们的后代。如果您希望排除整个子树,则应提供将匹配子树中所有元素的选择器,例如通过使用通用选择器: $ cssInliner -> addExcludedSelector ( ' .message-preview ' );
$ cssInliner -> addExcludedSelector ( ' .message-preview * ' );
->addExcludedCssSelector(string $selector)
- 与排除 HTML 节点的addExcludedSelector
相反,此方法排除内联 CSS 选择器。例如,如果您不希望 CSS 重置规则内联在每个 HTML 节点上(例如* { margin: 0; padding: 0; font-size: 100% }
),这非常有用。请注意,这些选择器必须与您要排除的选择器精确匹配。这意味着排除.example
不会排除p .example
。 $ cssInliner -> addExcludedCssSelector ( ' * ' );
$ cssInliner -> addExcludedCssSelector ( ' form ' );
->removeExcludedCssSelector(string $selector)
- 删除之前添加的排除选择器(如果有)。 $ cssInliner -> removeExcludedCssSelector ( ' form ' );
Emogrifier
类迁移到CssInliner
类使用Emogrifier
的旧代码:
$ emogrifier = new Emogrifier ( $ html );
$ html = $ emogrifier -> emogrify ();
使用CssInliner
的新代码:
$ html = CssInliner:: fromHtml ( $ html )-> inlineCss ()-> render ();
注意:在此示例中,旧代码删除带有display: none;
而新代码则不然,因为新旧类的默认行为在这方面有所不同。
使用Emogrifier
的旧代码:
$ emogrifier = new Emogrifier ( $ html , $ css );
$ emogrifier -> enableCssToHtmlMapping ();
$ html = $ emogrifier -> emogrify ();
使用CssInliner
和系列的新代码:
$ domDocument = CssInliner:: fromHtml ( $ html )-> inlineCss ( $ css )-> getDomDocument ();
HtmlPruner:: fromDomDocument ( $ domDocument )-> removeElementsWithDisplayNone ();
$ html = CssToAttributeConverter:: fromDomDocument ( $ domDocument )
-> convertCssToVisualAttributes ()-> render ();
Emogrifier 目前支持以下 CSS 选择器:
~
值(空格分隔的单词列表中的一个单词)|
(精确值匹配或前缀后跟连字符)^
的值(前缀匹配)$
的值(后缀匹配)*
的值(子字符串匹配)p:first-of-type
但不是*:first-of-type
)以下选择器尚未实现:
<style>
元素 - 包括(但不一定限于)以下内容:涉及以下选择器的规则不能应用为内联样式。但是,它们将被保留并复制到 HTML 中的<style>
元素中:
:hover
)::after
) @media
规则。媒体查询在响应式电子邮件设计中非常有用。请参阅媒体查询支持。但是,为了使它们有效,您可能需要向其中的某些声明添加!important
,以便它们覆盖已内联的 CSS 样式。例如,对于以下 CSS, @media
规则中的font-size
声明不会覆盖前一规则中p
元素的字体大小,之后内联为<p style="font-size: 16px;">
在 HTML 中,没有!important
指令(尽管如果 CSS 没有内联,就不需要!important
): p {
font-size : 16 px ;
}
@media ( max-width : 640 px ) {
p {
font-size : 14 px !important ;
}
}
@media
规则中定义的任何 CSS 自定义属性(变量)都不能应用于已内联和计算的 CSS 属性值。但是,使用自定义属性(使用var()
)的@media
规则仍然能够在支持自定义属性的电子邮件客户端中获取其值(从内联定义或@media
规则)。::after
)或动态伪类(例如:hover
)的选择器的 CSS 规则——这是不可能的。但是,此类规则将被保留并复制到<style>
元素,就像@media
规则一样,并应用相同的注意事项。<style>
块,但它不会抓取<link>
元素或@import
规则中引用的 CSS 文件(尽管它会让支持它们的电子邮件客户端保持完整)。请查看我们的 API 和弃用政策。
我们非常欢迎以错误报告、功能请求或拉取请求的形式做出贡献。请查看我们的贡献指南,了解有关如何为 Emogrifier 做出贡献的更多信息。
branch-alias
条目以指向即将发布的版本之后的版本。