Все, кто сталкивался с версткой писем, знают, что там по-прежнему используется табличная верстка, инлайновые стили, css хаки, устаревшие теги и т.д. И все это ради поддержки всех (или, вернее сказать, большинства) почтовых клиентов: различных версий Outlook, веб-интерфейсов почтовиков и мобильных почтовых клиентов.
Но индустрия не стоит на месте - все активнее для верстки писем применяются емейл-фреймворки. О них и пойдет речь дальше. Сравним 2 из них: MJML и TJML framework (хотел добавить еще и Zurb Foundation for email, но они в последних публикациях уже не говорят о поддержке outlook, да и в принципе устарели).
MJML - самый известный и популярный емейл-фреймворк, признанный сообществом. На его основе работают всевозможные визуальные емейл-билдеры, и по факту он является стандартом в зарубежном емейл-маркетинге, хотя в России не все о нем знают.
TJML framework - это мой емейл-фреймворк, который создавался на основе личного многолетнего опыта работы в сфере емейл-маркетинга. В нем я постарался учесть все те проблемы и сложности, с которыми сталкивается верстальщик писем. Идея была в том, чтобы не просто обеспечить “приемлемое отображение” в большинстве клиентов”, а дать свободу верстальщику, при этом не обременяя его вопросами совместимости с устаревшими почтовыми клиентами. Ну и, плюс ко всему, дать возможность заложить в единый код как html, так и AMP-версию письма. Но в этой статье речь пойдет пока что только о html.
Чтобы сравнить эти емейл-фреймворки, сверстаем следующее письмо, а потом посмотрим на получившийся код и качество отображения в различных почтовых клиентах.
Здесь есть все основные элементы, на которых можно проверить работу:
перестраивающиеся блоки (товарные карточки и заголовок с изображением на главном баннере);
масштабируемые блоки (в шапке письма);
использование фонового изображения (на баннере);
тексты;
кнопки.
Подключение и использование
MJML
Предоставляет несколько вариантов подключения на выбор:
playground прямо на сайте (самый простой и быстрый вариант для ознакомления);
приложение для Windows, Mac или Linux;
установка пакета через npm и использование его в привычной IDE;
готовые плагины для VSCode, Atom и Sublime Text.
TJML framework
playground для знакомства с инструментом;
подключение js и css файлов (по отдельности или js кодом из документации) и дальнейшая работа в привычной IDE;
Для продуктов JetBrains - phpStorm и webStorm - доступны подсказки и автокомплит через подключение web-types.json; также доступен плагин для VSCode.
Подготовительный этап
Для начала сделаем пустую заготовку письма:
MJML
<mjml>
<mj-head>
<mj-attributes>
<!-- укажем шрифт по-умолчанию -->
<mj-all font-family="Arial" />
</mj-attributes>
</mj-head>
<mj-body width="600px" background-color="#ffffff">
<!-- тело письма -->
</mj-body>
</mjml>
Весь код письма обрамляется тегом <mjml>
. Внутри присутствуют 2 раздела:<mj-head>
- здесь мы по аналогии с html кодом задаем какие-то общие стили, заголовок страницы и значения атрибутов по-умолчанию, чтобы в дальнейшем их не указывать у каждого тега. Мы указали шрифт по-умолчанию - Arial в коде. Раздел mj-head не является обязательным.<mj-body>
- этот раздел содержит тело письма и является обязательным.
TJML framework
<tjml>
<m-body bgcolor="#ffffff" font-family="Arial, sans-serif">
<m-head preheader="текст, который отображается рядом с темой в списке входящих до открытия в почтовике"></m-head>
<!-- тело письма -->
</m-body>
</tjml>
Здесь также есть общий обрамляющий тег <tjml>
, внутри которого находится обязательный тег <m-body>,
внутри которого уже находится все содержимое письма. Также в <m-body>
может быть необязательный тег <m-head>
, который позволяет задать параметры прехэдера письма. Параметры для текста по-умолчанию можно задать через атрибуты тега <m-body>
.
Приступим к верстке
MJML
В MJML есть строгая иерархия блоков - что и во что можно вкладывать. Например, mj-column может быть только внутри mj-section или mj-group, а mj-section - внутри mj-body или mj-wrapper. Это сильно ограничивает доступные структуры, которые можно построить, а, следовательно, и дизайн.
Для вставки первого блока с фоновой картинкой воспользуемся тегом mj-wrapper, указав отступы, радиус скругления и фоновую картинку:
<mj-wrapper padding="30px 20px" border-radius="10px" background-url="img/bg.jpg">
<!-- Содержимое блока -->
</mj-wrapper>
Логотип и номер телефона у нас вполне могут поместиться в строку на мобильном устройстве, поэтому сделаем масштабируемый (не перестраивающийся) блок. Для этого в mj-section необходимо добавить тег mj-group. В итоге получаем код:
<mj-section padding="0">
<mj-group>
<mj-column vertical-align="middle">
<mj-image align="left" src="img/logo.png" padding="0" width="132px" height="22px" alt="transistor"></mj-image>
</mj-column>
<mj-column vertical-align="middle">
<mj-text align="right" font-size="16px" color="#ffffff" font-weight="bold" padding="0px" padding-top="0">
<a href="#" style="text-decoration: none;color:#ffffff;">+1 877-635-4243</a>
</mj-text>
</mj-column>
</mj-group>
</mj-section>
Ниже в макете у нас заголовок и изображение ноутбука, которые необходимо перестраивать. Поэтому используем похожую структуру, но уже без mj-group.
<mj-section padding="30px 0 0">
<mj-column vertical-align="middle">
<mj-text align="left" font-size="36px" color="#ffffff" padding="0px">
The best<br />laptop deals
</mj-text>
</mj-column>
<mj-column vertical-align="middle">
<mj-image align="left" src="img/img.png" padding="0" width="280px" height="168px"></mj-image>
</mj-column>
</mj-section>
Блок с двумя товарами осложняется тем, что у товарных блоков есть фоновый цвет. И обычными инструментами расстояние между блоками сделать не получится. Нужно либо добавлять отступ через вспомогательный класс, либо использовать вставку произвольного html-кода. Оба этих решения несколько отходят от чистого использования фреймворка, поэтому сделаем отступ через дополнительную пустую колонку в 20 пикселей:
<mj-section padding="30px 0 20px">
<mj-column width="290px" background-color="#F5F5F7" padding="20px" border-radius="14px">
<mj-image align="center" src="img/item1.png" padding="0" width="180px" height="113px"></mj-image>
<mj-text align="center" font-size="22px" color="#222231" padding="10px 0 0">
$1,650.90
</mj-text>
<mj-text align="center" font-size="16px" color="#6a6a71" padding="5px 0 10px">
Laptop 15” 8GB Memory 512GB
</mj-text>
<mj-button background-color="#EA44A8" width="94px" height="40px" font-size="14px">
Buy
</mj-button>
</mj-column>
<mj-column width="20px"></mj-column>
<mj-column width="290px" background-color="#F5F5F7" padding="20px" border-radius="14px">
<mj-image align="center" src="img/item2.png" padding="0" width="180px" height="113px"></mj-image>
<mj-text align="center" font-size="22px" color="#222231" padding="10px 0 0">
$1,990.90
</mj-text>
<mj-text align="center" font-size="16px" color="#6a6a71" padding="5px 0 10px">
Tablet 11" 64GB Black
</mj-text>
<mj-button background-color="#EA44A8" width="94px" height="40px" font-size="14px">
Buy
</mj-button>
</mj-column>
</mj-section>
И остается только футер:
<mj-section>
<mj-column>
<mj-text align="left" font-size="10px" color="#bababa" padding="0">
If you prefer not to receive emails like this, you may unsubscribe<br />
© 2023 Company. All rights reserved.
</mj-text>
</mj-column>
</mj-section>
TJML framework
Здесь нет жесткой иерархии элементов. Фреймворк оперирует тремя абстракциями, на основе которых строится структура:
обертка (m-wrap) - применяется для задания фона, рамки, отступов и т.д., ограничения размера или же для указания выравнивания;
перестраивающиеся блоки (m-boxes и m-box);
Не перестраивающиеся блоки (m-row и m-column).
Данный подход позволяет реализовать в рамках письма любую структуру. Помимо тегов, отвечающих за структуру, есть текст (m-text), кнопка (m-button), картинка (m-img) и другие.
У первого блока есть фоновое изображение и закругления. Для его вставки будем использовать тег <m-wrap>
с атрибутами background-image, border-radius, а также зададим альтернативный фоновый цвет через bgcolor и отступы через padding.
<m-wrap width="600" padding="30px 20px" bgcolor="#D547A0" background-image="img/bg.jpg" border-radius="10px">
<!-- тело письма -->
</m-wrap>
Блоки, которые должны сжиматься, зададим через конструкцию не перестраивающихся блоков - m-row и m-column
<m-row width="100%">
<m-column align="left">
<m-img src="img/logo.png" width="132" height="22" alt=""></m-img>
</m-column>
<m-column align="right" valign="middle">
<m-text href="#" color="#ffffff" bold font-size="16px">+1 877-635-4243</m-text>
</m-column>
</m-row>
Перестраивающиеся блоки заголовка и изображения ноутбуков можно сделать через конструкцию m-boxes и m-box
<m-boxes align="left" valign="middle">
<m-box width="280" align="left">
<m-text color="#ffffff" font-size="36px">
The best<br />laptop deals
</m-text>
</m-box>
<m-box width="280">
<m-img src="img/img.png" width="280" height="168" alt=""></m-img>
</m-box>
</m-boxes>
Товарные карточки также представляют из себя перестраивающиеся блоки. Для отступов будем использовать вложенные m-wrap с заданием желаемых размеров и фона.
<m-wrap width="620">
<m-boxes>
<m-box width="310">
<m-wrap width="290" bgcolor="#F5F5F7" border-radius="14px" padding="20px">
<m-img src="img/item1.png" width="180" height="113" alt=""></m-img>
<m-wrap padding="10px 0">
<m-text color="#222231" font-size="22px" line-height="26px">$1,650.90</m-text>
<m-text color="#6A6A71" font-size="16px" line-height="20px">Laptop 15” 8GB Memory 512GB</m-text>
</m-wrap>
<m-button color="#ffffff" border-radius="6px" bgcolor="#EA44A8" width="94" height="40">Buy</m-button>
</m-wrap>
<m-padding size="20"></m-padding>
</m-box>
<m-box width="310">
<m-wrap width="290" bgcolor="#F5F5F7" border-radius="14px" padding="20px">
<m-img src="img/item2.png" width="180" height="113" alt=""></m-img>
<m-wrap padding="10px 0">
<m-text color="#222231" font-size="22px" line-height="26px">$1,990.90</m-text>
<m-text color="#6A6A71" font-size="16px" line-height="20px">Tablet 11" 64GB Black</m-text>
</m-wrap>
<m-button color="#ffffff" border-radius="6px" bgcolor="#EA44A8" width="94" height="40">Buy</m-button>
</m-wrap>
<m-padding size="20"></m-padding>
</m-box>
</m-boxes>
</m-wrap>
И остался футер
<m-wrap width="620" padding="20px 10px" align="left">
<m-text font-size="10px" color="#BABABA">
If you prefer not to receive emails like this, you may unsubscribe<br />
© 2023 Company. All rights reserved.
</m-text>
</m-wrap>
Сравниваем результаты
Главное в подобном инструменте - это конечно, отрендеренная (собранная) верстка: качество кода, его размер, читаемость и кроссплатформенность.
Размер кода
Начнем с размеров. Почему это важный показатель? Дело в том, что Gmail обрезает письма, которые превышают 102kb. Это не только сломает письмо визуально, но и не позволит отследить открытия таких писем, так как трекинг-пиксели обычно добавляются в самом конце перед закрывающим body. То есть вы получите заниженные показатели OR.
Для сравнения сжатия будем использовать встроенные инструменты сжатия каждого из фреймворков:
MJML | TJML framework | |
Без сжатия | 22 Кб | 14,1 Кб |
С сжатием | 14,8 Кб | 10,7 Кб |
Отображение в разных почтовиках
Для начала сравним отображение в веб-интерфейсе Gmail:
Здесь оба фреймворка показали себя хорошо. Попробуем что-нибудь посложнее - например, отображение в десктопном приложении Outlook, как в самом “капризном” почтовом клиенте:
Здесь разница отображения уже сильно заметна. Главным образом в MJML мы видим проблемы с отступом у блока с фоновым изображением. Это связано с особенностями Outlook при обработке padding внутри vml (именно vml используется в обоих фреймворках для отображения фоновых изображений для Outlook. Вообще, vml - это язык векторной разметки документа от Microsoft).
Также заметна разница в отображении кнопок. В TJML framework для кнопок используется vml (где это возможно), поэтому мы видим четкое соответствие макету по размерам и сохранение закруглений. В MJML используется ячейка таблицы. В данном случае мы видим дополнительные отступы, которые появились у этой ячейки, что увеличило высоту кнопок.
Часто можно услышать - “Да кому нужен этот аутлук? Им никто не пользуется”. Да, для b2c рассылок, в среднем, на открытия с Outlook приходится менее 5%. Но картина резко меняется, если мы говорим про b2b рассылки. А также, по опыту работы в агентстве, могу заметить, что зачастую сам заказчик использует именно Outlook, и присланные тесты смотрит именно в нем.
В MJML используется подход “mobile first”. То есть структура изначально соответствует мобильной версии письма, а с помощью медиа-запросов уже формируется десктопная версия. Подход неплохо работает в большинстве почтовых клиентов и обеспечивает отличное отображение в мобильных приложениях даже без поддержки медиа-запросов. Однако в России очень популярна Yandex-почта, которая занимает 2 место после mail.ru, и при этом не поддерживает медиа-запросы - ни в веб интерфейсе, ни в мобильных приложениях.
Для полноты картины также стоит показать мобильную адаптацию:
TJML framework, наоборот, не использует медиа-запросы для адаптации по умолчанию. Поэтому мы видим карточки исходного размера, а не на всю ширину, как в MJML. При необходимости это можно изменить, используя классы и медиа-запросы в разделе m-style. Также заметно, что отличается выравнивание фонового изображения по умолчанию. Как в MJML, так и в TJML framework его можно изменить с помощью соответствующего атрибута.
Дополнительные инструменты
MJML
MJML предлагает нестандартные компоненты для использования в письмах:
mj-accordion для создания аккордеонов;
mj-carousel для создания каруселей.
Но эти элементы мало где работают - главным образом только в стандартном приложении почты на iPhone и на Mac.
Это проект имеет открытый исходный код и активно поддерживается сообществом, поэтому можно найти большое количество компонентов, например:
mj-chart для добавления графиков;
mj-qr-code - для добавления QR-кодов.
TJML framework
Главным отличием от всех прочих емейл-фреймворков является то, что он формирует не только html версию письма, но также AMP и поддерживает ряд AMP-компонентов (карусели, аккордеоны, формы, amp-листы). И в отличие от MJML они будут работать в почтовых клиентах от gmail, mail.ru и yahoo (при выполнении ряда требований, но в особенности AMP здесь вдаваться не буду).
Для разработчика также есть вспомогательные инструменты для достижения наилучшего результата за минимальное время:
инструмент pixel perfect - наложение макета под верстку с одним из режимов смешивания для точной верстки “пиксель в пиксель”;
тестирование темной темы.
С появлением темной темы и автоматическим перекрашиванием писем в мобильных почтовых клиентах у верстальщиков и дизайнеров появилась еще одна проблема. И как обычно это бывает - у всех это перекрашивание работает немного по разному. Поэтому при разработке вспомогательных инструментов фреймворка я сделал особый акцент на это и предусмотрел 2 варианта - обычная темная тема (с инверсией яркости у светлых элементов), а также режим полной инверсии яркости, характерный для Gmail на iOS (он изначально темные письма перекрашивает в светлые).
TJML фреймворк доступен без каких-либо ограничений и поможет как значительно сократить время на разработку писем, так и снизить порог вхождения в емейл-верстку. Я постарался вложить свой опыт в сфере емейл-маркетинга и емейл-верстки в инструмент который поможет абстрагироваться от привычных емейл костылей, вроде условных комментариев, vml и табличной верстки и оперировать уже структурными элементами. А также позволит стереть границу между интерактивными amp и статичными html письмами. Но это уже тема для другой статьи).
Я продолжаю развивать этот инструмент и буду рад, если он окажется полезен).