н. e•mog•ri•fi•er [ē-'mä-grƏ-,fī-Ər] — утилита для полного изменения характера или внешнего вида электронной почты в формате HTML, особенно. особенно фантастическим или причудливым образом
Emogrifier преобразует стили CSS во встроенные атрибуты стиля в вашем HTML-коде. Это обеспечивает правильное отображение в программах чтения электронной почты и мобильных устройствах, на которых отсутствует поддержка таблиц стилей.
Эта утилита была разработана как часть Intervals для решения проблем, возникающих у некоторых почтовых клиентов (а именно Outlook 2007 и GoogleMail), когда дело касается способа обработки стилей, содержащихся в электронных письмах в формате HTML. Как уже знают многие веб-разработчики и дизайнеры, некоторые почтовые клиенты печально известны отсутствием поддержки CSS. Хотя предпринимаются попытки разработать общие стандарты электронной почты, до их реализации еще далеко.
Основная проблема несовместимых почтовых клиентов заключается в том, что большинство из них склонны учитывать только встроенный CSS, отбрасывая все элементы <style>
и ссылки на таблицы стилей в элементах <link>
. Emogrifier решает эту проблему, преобразуя стили CSS во встроенные атрибуты стиля в вашем HTML-коде.
Emogrifier автоматически преобразует ваш HTML, анализируя CSS и вставляя определения CSS в теги HTML на основе ваших селекторов CSS.
Чтобы установить emogrifier, либо добавьте pelago/emogrifier
в раздел require
в composer.json
вашего проекта, либо вы можете использовать композитор, как показано ниже:
composer require pelago/emogrifier
См. https://getcomposer.org/ для получения дополнительной информации и документации.
Самый простой способ использования класса CssInliner
— создать экземпляр с исходным HTML, встроить внешний CSS и затем получить полученный HTML:
use Pelago Emogrifier CssInliner ;
…
$ visualHtml = CssInliner:: fromHtml ( $ html )-> inlineCss ( $ css )-> render ();
Если внешнего файла CSS нет и весь CSS находится внутри элементов <style>
в HTML, вы можете опустить параметр $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
), которые вы можете использовать для дальнейшего изменения HTML после встраивания CSS. (Более подробную информацию о классах можно найти в разделах ниже.) 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
встроит этот CSS в (надуманный) HTML <html><body><p></p></body></html>
, он будет выглядеть так:
< 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
может уменьшить размер HTML, удалив элементы с объявлением стиля display: none
и/или удалив классы из необязательных атрибутов class
.
Его можно использовать следующим образом:
use Pelago Emogrifier HtmlProcessor HtmlPruner ;
…
$ prunedHtml = HtmlPruner:: fromHtml ( $ html )-> removeElementsWithDisplayNone ()
-> removeRedundantClasses ( $ classesToKeep )-> render ();
Метод removeRedundantClasses
принимает список разрешенных имен классов, которые следует сохранить. Если это этап постобработки после встраивания CSS, вы можете альтернативно использовать removeRedundantClassesAfterCssInlined
, передав ему экземпляр CssInliner
, встроивший CSS (и заставив 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 >
Метод removeRedundantClassesAfterCssInlined
(или removeRedundantClasses
), если он вызван после removeElementsWithDisplayNone
, удалит класс -emogrifier-keep
.
Существует несколько параметров, которые вы можете установить для экземпляра CssInliner
перед вызовом метода inlineCss
:
->disableStyleBlocksParsing()
— по умолчанию CssInliner
захватывает все блоки <style>
в HTML и применяет стили CSS как встроенные атрибуты «style» к HTML. Блоки <style>
будут удалены из HTML. Если вы хотите отключить эту функцию, чтобы CssInliner
оставил эти блоки <style>
в HTML и не анализировал их, вам следует использовать эту опцию. Если вы используете эту опцию, содержимое блоков <style>
не будет применяться как встроенные стили, и любой CSS, который вы хотите использовать CssInliner
, должен быть передан, как описано в разделе «Использование» выше.->disableInlineStyleAttributesParsing()
— по умолчанию CssInliner
сохраняет все атрибуты «стиля» в тегах HTML-кода, который вы ему передаете. Однако, если вы хотите удалить все существующие встроенные стили в HTML до применения CSS, вам следует использовать эту опцию.->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)
— в отличие от addExcludedSelector
, который исключает узлы HTML, этот метод исключает встраивание селекторов 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 ();
NB: В этом примере старый код удаляет элементы с 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>
в HTML:
:hover
)::after
) @media
. Медиа-запросы могут быть очень полезны при создании адаптивного дизайна электронной почты. См. поддержку медиа-запросов. Однако для того, чтобы они были эффективными, вам может потребоваться добавить !important
к некоторым объявлениям внутри них, чтобы они переопределяли встроенные стили CSS. Например, в следующем CSS объявление font-size
в правиле @media
не будет переопределять размер шрифта для элементов p
из предыдущего правила после того, как оно было встроено как <p style="font-size: 16px;">
в HTML без директивы !important
(хотя в !important
не было бы необходимости, если бы CSS не был встроенным): p {
font-size : 16 px ;
}
@media ( max-width : 640 px ) {
p {
font-size : 14 px !important ;
}
}
@media
, нельзя применять к значениям свойств CSS, которые были встроены и оценены. Однако правила @media
использующие настраиваемые свойства (с помощью var()
), по-прежнему смогут получать свои значения (из встроенных определений или правил @media
) в почтовых клиентах, поддерживающих настраиваемые свойства.::after
) или динамическими псевдоклассами (такими как :hover
) — это невозможно. Однако такие правила будут сохранены и скопированы в элемент <style>
, как и правила @media
, с теми же оговорками.<style>
из вашего HTML, но он не будет захватывать файлы CSS, указанные в элементах <link>
или правилах @import
(хотя он оставит их нетронутыми для почтовых клиентов, которые их поддерживают).Пожалуйста, ознакомьтесь с нашим API и политикой прекращения поддержки.
Вклад в виде отчетов об ошибках, запросов на добавление функций или запросов на включение более чем приветствуется. Пожалуйста, ознакомьтесь с нашими правилами участия, чтобы узнать больше о том, как внести свой вклад в Emogrifier.
branch-alias
, чтобы она указывала на выпуск после предстоящего выпуска.