14 ноября 2024 г.

MJML или TJML: испытываем емейл-фреймворки на практике

Время чтения: 12 минут

Создание электронных писем, которые корректно отображались бы во всех почтовых клиентах, было настоящей головной болью. Табличная верстка, устаревшие теги и CSS-хаки были неотъемлемой частью этого процесса.

Сейчас все изменилось: появились емейл-фреймворки, которые упрощают эту задачу. В этом обзоре мы рассмотрим два из них: MJML и TJML, чтобы определить, какой лучше подходит для создания эффективных email-рассылок.

Что это за фреймворки?

MJML — это наиболее популярный фреймворк для писем. Он лежит в основе многих визуальных конструкторов и фактически стал стандартом международного емейл-маркетинга, хотя в России не так известен.

TJML — это фреймворк от Pixcraft, созданный на основе богатого опыта в email-маркетинге. Это инструмент, который решает многие проблемы, с которыми сталкиваются верстальщики ежедневно.

С TJML вы можете не беспокоиться о совместимости с разными почтовыми клиентами и сосредоточиться на создании красивых и адаптивных писем. Кроме того, TJML позволяет объединить в одном коде HTML и AMP-версии письма.

Какой фреймворк выбрать?

Чтобы разобраться, давайте на практике попробуем каждый из них. После этого проанализируем полученный код и оценим качество отображения письма в различных почтовых клиентах.

Сверстаем письмо, включающее в себя адаптивные блоки (товарные карточки и баннеры с заголовками), масштабируемые блоки (элементы шапки письма), фоновые изображения, текст и кнопки.

Пример письма

Подключаем фреймворк

Как подключать MJML:

  • Онлайн-песочница. Самый простой способ попробовать MJML — это воспользоваться онлайн-редактором прямо на сайте. Подойдёт для тех, кто хочет быстро ознакомиться с возможностями фреймворка или создать простой емейл.
  • Десктопная версия. Для более масштабных задач предлагается приложение для основных операционок (Windows, macOS, Linux).
  • Плагины. Если вы пользуетесь популярными редакторами кода, такими как VSCode, Atom или Sublime Text, то для MJML есть специальные плагины.
  • Установка через npm. MJML можно установить через npm и использовать в любой удобной среде разработки.

Как подключить TJML:

Онлайн-песочница. Используйте playground для быстрого создания и тестирования писем. Можно писать код, сразу видеть результат и быстро вносить правки, не выходя из браузера.
Подключение как JS-библиотеки. Если вы предпочитаете работать в привычной среде разработки, то можете подключить JS-библиотеку. Все инструкции по подключению вы найдете в документации.
Плагин для VSCode. Это расширение предлагает автозаполнение и всплывающие подсказки для всех тегов и атрибутов TJML.
Автокомплит для PhpStorm и WebStorm через Web-Types. Вы можете подключить web-types.json, чтобы получить подсказки по тегам и доступным атрибутам.

Готовимся к верстке

Начнем с пустой заготовки емейла.

С MJML:

1
2
3
4
5
6
7
8
9
10
11
<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>. Внутри есть два раздела: <mj-head> и <mj-body>.

  • В необязательном разделе <mj-head> задаются общие стили, заголовок страницы и значения атрибутов по умолчанию, что позволяет не указывать их для каждого тега. В нашем примере установлен шрифт по умолчанию — Arial.
  • Тег <mj-body> содержит основное содержание письма и является обязательным элементом структуры.

C TJML:

1
2
3
4
5
6
<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>. Задаем отступы, радиус скругления и изображение.

1
2
3
<mj-wrapper padding="30px 20px" border-radius="10px" background-url="img/bg.jpg">
    <!-- Содержимое блока -->
</mj-wrapper>

Лого и номер телефона поместятся в одной строке на мобильном устройстве, поэтому создадим масштабируемый блок, который не будет перестраиваться. В <mj-section> добавим <mj-group>.

Что получается в итоге:

1
2
3
4
5
6
7
8
9
10
11
12
<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.

1
2
3
4
5
6
7
8
9
10
<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 />choice
         </mj-text>
   </mj-column>
   <mj-column vertical-align="middle">
         <mj-image align="left" src="img/img.png" padding="0" width="280px" height="234px"></mj-image>
   </mj-column>
</mj-section>

Блок с двумя товарами сложнее из-за фонового цвета у товарных карточек. Простым способом задать расстояние между ними нельзя.

Есть два варианта: добавлять отступ с помощью вспомогательного класса или вставлять собственный HTML-код.

Оба этих метода выходят за рамки стандартного использования фреймворка, поэтому добавим отступ, вставив пустую колонку шириной в двадцать пикселей.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<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="116px"></mj-image>
        <mj-text align="center" font-size="22px" color="#222231" padding="10px 0 0">
            $1,560.90
        </mj-text>
        <mj-text align="center" font-size="16px" color="#6a6a71" padding="5px 0 10px">
            Game console White
        </mj-text>
        <mj-button background-color="#6a66d3" width="94px" height="40px" font-size="14px">
            Buy
        </mj-button>
     </mj-column>
     <mj-column width="20px"><mj-text></mj-text></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="116px"></mj-image>
        <mj-text align="center" font-size="22px" color="#222231" padding="10px 0 0">
            $1,890.90
        </mj-text>
        <mj-text align="center" font-size="16px" color="#6a6a71" padding="5px 0 10px">
            Monitor 27” IPS LED FHD
        </mj-text>
        <mj-button background-color="#6a66d3" width="94px" height="40px" font-size="14px">
            Buy
        </mj-button>
     </mj-column>
</mj-section>

Дальше идет футер.

1
2
3
4
5
6
7
8
<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 />
            © 2024 Company. All rights reserved.
        </mj-text>
     </mj-column>
</mj-section>

С TJML:

В этом фреймворке жёсткая иерархия элементов отсутствует. Он предлагает три основные абстракции для создания структуры:

  • обертка (m-wrap), которая задает фон, рамки, отступы, ограничения по размеру и выравнивание;
  • перестраивающиеся блоки (m-boxes и m-box);
  • не перестраивающиеся блоки (m-row и m-column).

Такой подход обеспечивает гибкость в создании структуры письма. Помимо структурных тегов, доступны такие элементы, как текст (m-text), кнопка (m-button), изображение (m-img) и другие.

Первый блок требует фонового изображения и скругленных углов. Используем тег <m-wrap>, задав атрибуты background-image, border-radius, а также альтернативный цвет (bgcolor) и отступы (padding).

1
2
3
<m-wrap width="600" padding="30px 20px" bgcolor="#473fac" background-image="img/bg.jpg" border-radius="10px">
    <!-- тело письма --> 
</m-wrap>

Блоки, требующие сжатия, задаются с использованием m-row и m-column.

1
2
3
4
5
6
7
8
<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.

1
2
3
4
5
6
7
8
9
10
<m-boxes align="left" valign="middle">
    <m-box width="280" align="left">
        <m-text color="#ffffff" font-size="36px">
            The best<br />choice
        </m-text>
    </m-box>
    <m-box width="280">
        <m-img src="img/img.png" width="280" height="234" alt=""></m-img>
    </m-box>
</m-boxes>

Карточки товаров тоже являются перестраивающимися блоками. Чтобы задать отступы, применим вложенные m-wrap с нужными размерами и фоновым цветом.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<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="116" alt=""></m-img>
            <m-wrap padding="10px 0">
                <m-text color="#222231" font-size="22px" line-height="26px">$1,560.90</m-text>
                <m-text color="#6A6A71" font-size="16px" line-height="20px">Game console White</m-text>
            </m-wrap>
            <m-button color="#ffffff" border-radius="6px" bgcolor="#6a66d3" 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="116" alt=""></m-img>
            <m-wrap padding="10px 0">
                <m-text color="#222231" font-size="22px" line-height="26px">$1,890.90</m-text>
                <m-text color="#6A6A71" font-size="16px" line-height="20px">Monitor 27” IPS LED FHD</m-text>
            </m-wrap>
            <m-button color="#ffffff" border-radius="6px" bgcolor="#6a66d3" width="94" height="40">Buy</m-button>
        </m-wrap>
        <m-padding size="20"></m-padding>
    </m-box>
</m-boxes>
</m-wrap>

И, наконец, идет футер.

1
2
3
4
5
6
<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 />
   © 2024 Company. All rights reserved.
   </m-text>
</m-wrap>

Что получилось

Ключевым аспектом фреймворка является качество готовой верстки, включая чистоту кода, его объем, читаемость и отображение в различных почтовых клиентах.

Размер

Gmail автоматически обрезает письма, если их размер превышает 102 КБ. Это не только испортит внешний вид, но и затруднит отслеживание OR, так как пиксели для трекинга обычно добавляются в конце перед закрывающим тегом <body>. Т.е. «раздутый» код приведет к снижению статистики открытий.

Для оценки сжатия используем встроенные инструменты сжатия каждого фреймворка.

TJMLMJML
Сжатый код11,17 КБ14,84 КБ
Несжатый код13,52 КБ22,35 КБ


Как отображается в разных почтовых клиентах

В Gmail:

Отображение в Gmail

Теперь давайте попробуем что-то более сложное — например, посмотрим, как письмо выглядит в десктопной версии Outlook. Проблемы с отображением в этой программе — явление довольно частое.

Для B2C-рассылок отображение в Outlook может быть не столь критичным, т.к. в среднем его показатель открытий не превышает 5%. Однако в контексте B2B-рассылок наблюдается совершенно иная картина. Кроме того, заказчики зачастую проверяют тестовые письма именно в Outlook. Поэтому пренебрегать этим почтовиком не стоит.

Отображение в Outlook

В этом случае различия в отображении становятся очевидными. В MJML мы сталкиваемся с проблемами отступов у блока с фоном. Это происходит из-за специфики работы Outlook с padding внутри VML.

Кнопки тоже отображаются по-разному. В TJML для их создания по возможности используется VML, что позволяет добиться точного соответствия размерам макета и сохранить закругленные углы. В MJML кнопки формируются с помощью таблицы, из-за чего высота кнопок увеличивается из-за дополнительных отступов.

В фреймворке MJML применяется принцип «mobile first», что означает, что структура письма изначально ориентирована на мобильные устройства, а версия для десктопов создается с помощью медиа-запросов. Принцип показывает неплохие результаты во многих почтовых клиентах и позволяет добиться качественного отображения на мобильных устройствах, даже если медиа-запросы не поддерживаются. Однако стоит учитывать, что Yandex не поддерживает медиа-запросы ни в своей веб-версии, ни в мобильных приложениях — а этот почтовый сервис занимает второе место по популярности в России.

Десктопная версия Yandex:

Отображение в Yandex

Мобильная версия:

Отображение в мобильной версии

В отличие от MJML, TJML изначально не применяет медиа-запросы для адаптации. Поэтому карточки отображаются в своем исходном размере, а не растягиваются на весь экран. При желании это можно исправить, добавив классы и медиа-запросы в m-style.

Также отличается выравнивание фона. В обоих фреймворках, MJML и TJML, его легко изменить, используя соответствующий атрибут.

Какие еще есть инструменты

Фреймворк TJML отличается от других тем, что создает не только HTML-версию письма, но и AMP-версию, поддерживающую такие AMP-компоненты, как карусели, аккордеоны, формы и списки AMP и др. В отличие от MJML, эти элементы будут корректно работать в почтовых клиентах Gmail, Mail.ru,Yahoo и AOL.

О том, как правильно внедрить AMP-письма в вашу емейл-стратегию, читайте здесь.

Также есть дополнительные инструменты для удобства:

  • Pixel Perfect позволяет убедиться, что каждый элемент на экране расположен точно так, как было задумано дизайнером, вплоть до отдельного пикселя. Пользователи могут загружать графические макеты и регулировать их прозрачность, чтобы визуально сопоставить с версткой. Это позволяет разработчикам точно подстраивать размеры, отступы и другие параметры, добиваясь идеального совпадения «пиксель в пиксель» между дизайном и реализацией.
  • Тестирование темной темы. Поскольку многие пользователи мобильных устройств предпочитают темное оформление, возникла необходимость адаптировать электронные письма под почтовые клиенты, которые по-разному реализуют эту функцию. Для решения этой задачи мы добавили два режима отображения в темной теме: стандартный (с инверсией светлых элементов) и режим полной инверсии, аналогичный Gmail для iOS.

Заключение

Использование email-фреймворков в значительной степени позволяет ускорить и упростить процесс верстки писем, при этом позволяет гибко управлять структурой и отображением.

TJML — это практичное и удобное решение для создания емейлов, ориентированное на реальные потребности верстальщиков. По сравнению с MJML, TJML обеспечивает больше свободы в работе и позволяет избежать проблем с совместимостью с устаревшими почтовыми клиентами. Он также дает возможность создавать как HTML, так и AMP-версии в одном коде.

Если вы ищете инструмент, который упростит процесс разработки, TJML станет отличным выбором для вашего бизнеса.

Поделиться: