dot-to-dot-game-cover
27 сентября 2024

Пошаговый гайд по созданию игры «Соедините точки» для писем (с примерами кода)

Создать эксклюзивные письма
Оглавление
  1. Как устроена игра
  2. AMP-версия
  3. Интерактивная HTML-версия
  4. Фолбэк-версия
  5. В завершение
1.
Как устроена игра

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

Игра «Соедините точки» в действии

Мы возвращаем эти приятные воспоминания в нашей новой интерактивной механике для писем под названием «Соедините точки». Этот интерактивный элемент может найти множество применений в email-маркетинге:

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

В этой статье мы подробно расскажем, как создать полноценную игру, которая будет включать в себя следующее:

  • AMP-версию игры с пятью изображениями;
  • интерактивную HTML-версию с теми же пятью изображениями;
  • фолбэк-версию для почтовых клиентов, не поддерживающих интерактивность.

Давайте перейдем к гайду.

Как устроена игра

Для начала стоит обсудить принцип функционирования игры в целом. В нашем примере получателю нужно нарисовать ракету. Сам рисунок разделен на несколько сегментов, между которыми находятся точки. Далее нам нужен каждый сегмент, а точки прокладываются отдельно (а именно, для каждого сегмента 1-2, 2-3, 3-4 и т. д. создается отдельный блок, который двигается и поворачивается под нужным углом). Соединив все это, получатели могут завершить изображение линиями, как будто они были нарисованы от руки.

AMP-версия

Начнем с добавления пустой структуры и выбора «Показывать в AMPHTML».

Подготовка структуры для игры

После этого добавьте в нее блок «HTML» и введите следующий код:

<style amp-custom>
    .dot-amp .dot-container {
        background: url(https://zlnfb.stripocdn.email/content/guids/CABINET_c102d17d796d323a0ee84181252016915f4177c79c86a55019b0dccf636e6f33/images/bg.png) no-repeat top center;
        background-size: contain;
        width: 300px;
        height: 450px;
        margin: 0 auto;
        position: relative;
    }

    .dot-amp .circle {
        display: inline-block;
        width: 10px;
        height: 10px;
        background: #000;
        border-radius: 50%;
    }

    .dot-amp .active .circle,
    .dot-amp .dot:hover .circle {
        background: blue;
    }

    .dot-amp .number {
        display: block;
        position: absolute;
        right: -10px;
        line-height: 10px;
    }

    .dot-amp .line {
        background: #000;
        width: 3px;
        height: 100%;
        position: absolute;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
    }

    .dot-amp .dot {
        display: block;
        cursor: pointer;
        padding: 10px;
        position: absolute;
        bottom: -18px;
        left: 50%;
        transform: translate(-50%, 0);
        line-height: 10px;
    }

    .dot-amp .block-1-2 {
        width: 7.50%;
        height: 20.17%;
        position: absolute;
        top: 1.67%;
        right: 17.75%;
        transform: rotate(-23deg);
    }

    .dot-amp .dot-1 {
        top: -14px;
        bottom: auto;
    }

    .dot-amp .dot-1 .number {
        transform: rotate(23deg);
    }

    .dot-amp .dot-2 .number {
        transform: rotate(23deg);
    }

    .dot-amp .block-2-3 {
        width: 7.50%;
        height: 16.83%;
        position: absolute;
        transform: rotate(-5deg);
        top: 21.83%;
        right: 10.50%;
    }

    .dot-amp .dot-3 .number {
        transform: rotate(5deg);
    }

    .dot-amp .result {
        padding: 20px 0;
        text-align: center;
    }

    @media only screen and (max-width: 600px) {
        .dot-amp .dot-container {
            width: 250px;
            height: 375px;
        }
    }
</style>
<div class="dot-amp">
    <div class="dot-container">
        <div class="block-2-3">
            <div class="line line-2-3" hidden [hidden]="dot2!=1 || dot3!=1"></div>
            <label role="button" tabindex="3" on="tap:AMP.setState({dot3:1, active:3})" class="dot dot-3" [class]="active == 3 ? 'dot dot-3 active' : 'dot dot-3'">
            	<span class="number">3</span>
            	<span class="circle"></span>
            </label>
        </div>
        <div class="block-1-2">
            <div class="line line-1-2" hidden [hidden]="dot1!=1 || dot2!=1"></div>
            <label role="button" tabindex="1" on="tap:AMP.setState({dot1:1, active:1})" class="dot dot-1" [class]="active == 1 ? 'dot dot-1 active' : 'dot dot-1'">
            	<span class="number">1</span>
            	<span class="circle"></span>
            </label>
            <label role="button" tabindex="2" on="tap:AMP.setState({dot2:1, active:2})" class="dot dot-2" [class]="active == 2 ? 'dot dot-2 active' : 'dot dot-2'">
            	<span class="number">2</span>
            	<span class="circle"></span>
            </label>
        </div>
    </div>
    <div class="result" hidden [hidden]="[dot1,dot2,dot3].indexOf(null) != -1">
        <h2 style="padding-bottom:15px">Congratulations!</h2>
        <p>Here's your personal promo code GAMIFICATION for 15% OFF sitewide.</p>
    </div>
</div>

На данный момент в коде 3 точки и 2 сегмента (позже их будет добавлено больше для придания игре законченного вида, как это было показано в демонстрационной GIF-ке). В макете блоки названы сегментами block-1-2, block-2-3 и так далее. Первый блок 1-2 состоит из линии и двух точек №1 и №2. Во всех остальных блоках будет линия и одна точка (в блоке 2-3 точка №3, в блоке 3-4 точка №4 и так далее).

Первый шаг в игре

Давайте рассмотрим один из блоков поближе.

На игровом блоке с точками

Первый элемент — div; это наша линия. Она имеет атрибуты hidden [hidden]="dot2!=1 || dot3!=1", где:

  • hidden — скрывает элемент;
  • [hidden] — задает условие, когда скрывать элемент (в нашем примере: скрывать, пока dot2 и dot3 не станут равны 1).

Далее следует тег label, который является точкой 3. Он имеет следующие атрибуты: role="button" tabindex="3" on="tap:AMP.setState({dot3:1, active:3})" [class]="active == 3 ? 'dot dot-3 active' : 'dot dot-3'", где:

  • role="button" — атрибут, который добавляется к элементу и работает как кнопка;
  • tabindex="3" — обязательный атрибут при наличии role="button", так как он задает последовательность получения фокуса при переключении между элементами с помощью клавиши табуляции;
  • on="tap:AMP.setState({dot3:1, active:3})" — обработчик события «клик» (on="tap:”);
  • dot3 — переменная, которая изначально имеет нулевое значение, но когда получатель кликает на эту точку, в переменную записывается значение 1, что помогает понять, на какую точку кликнул пользователь;
  • active — переменная, которая нужна для выделения точки, когда она активна; мы записываем в нее номер точки, на которую кликнул пользователь;
  • [class]="active == 3 ? 'dot dot-3 active' : 'dot dot-3'" — атрибут, в котором записывается условие отображения классов: если значение переменной active равно 3, то добавляется точка активного класса dot-3, в противном случае остается только точка класса dot-3.

Остальные сегменты (кроме 1-2) должны иметь ту же схему, только номера меняются в соответствии с номерами точек. Самый первый сегмент 1-2 отличается тем, что в нем есть сразу 2 точки (№1 и №2).

Код всех точек в игре

Сообщение о завершении игры

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

Завершающее сообщение

Он имеет атрибут [hidden]="[dot1,dot2,dot3].indexOf(null) != -1", который скрывает элемент при выполнении условия. В нашем примере блок будет скрыт, если хотя бы одна из переменных, dot1, dot2 и dot3, имеет нулевое значение (так будет, если точка не была кликнута). Чтобы блок отображался в кастомизированной игре с заданным количеством точек, все они должны быть перечислены здесь.

Разбираемся со стилями

Теперь поговорим о том, как выглядит игра, то есть о ее коде стилей. Ниже вы видите код, который задает фоновое изображение ракеты и размер блока для десктопной версии. В результате, чтобы установить свое собственное фоновое изображение для игры, вы должны изменить ссылку в выделенной области на ссылку вашего изображения.

Ссылка на фоновое изображение

Важное примечание: чтобы заменить наше изображение своим, его нужно подготовить, как в нашем примере. Также необходимо изменить размер блока, если ваше изображение имеет другие пропорции.

Десктопная версия игры в нашем примере имеет следующие размеры:

Размеры десктопной версии

Мобильный размер нашей игры обозначен этой частью кода:

Код размера мобильной версии игры

Тем временем цвета для точек по умолчанию и для точек при наведении задаются в этой части кода:

Код для цвета и размера точек

Цвет линий между точками задается в этом фрагменте кода:

Цвет для линий между точками

Расположение линий с помощью стилей и их кастомизация

Теперь самая сложная часть стилей — та, что отвечает за угол, под которым идут линии и, по сути, помогает создать рисунок:

Код позиционирования линий

Этот фрагмент кода задает размеры, координаты и наклоны каждого сегмента. Поскольку мы поворачиваем весь блок с помощью (transform: rotate(-23deg)), числа в нем также поворачиваются. Чтобы они выглядели ровно, мы выравниваем каждое число обратно с помощью стиля трансформации, а именно rotate(23deg).

Все значения задаются в процентах, чтобы их не нужно было менять на мобильных устройствах.

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

Вы можете сразу указать размеры в процентах или выбрать размеры в пикселях, а затем преобразовать их в проценты. Проценты вычисляются относительно контейнера с игрой (dot-container). В нашем примере его размеры составляют 300 px в ширину и 450 px в высоту.

Возьмем, к примеру, размеры блока 1-2: ширина 23 px, высота 90 px.

Мы рассчитываем ширину блока относительно ширины контейнера с игрой и высоту относительно высоты.

Для ширины существует формула расчета:

  • 23*100/300 = 7,67% — это значение записывается в ширину блока 1-2.

Для определения высоты используется следующая формула:

  • 90*100/450 = 20% — это значение записывается в высоту блока 1-2.

Значения «left» и «top» можно сразу задать в процентах или преобразовать из пикселей по той же формуле: для left или right — относительно ширины контейнера, а для top или bottom — относительно высоты контейнера.

Таким образом, вам необходимо добавить все нужные блоки с точками.

Интерактивная HTML-версия

Следующий шаг нашего гайда — интерактивная HTML-версия, созданная с помощью HTML5 и CSS3. Продолжайте работать с тем же шаблоном, где мы создавали AMP-версию. Добавьте еще одну пустую структуру. Выделите ее и выберите опцию «Показывать только в HTML».

Подготовка структуры для HTML-версии

Когда все будет готово, добавьте в нее блок «HTML» и вставьте следующий код:

<style>
    .dot-html .dot-container {
        background: url(https://zlnfb.stripocdn.email/content/guids/CABINET_c102d17d796d323a0ee84181252016915f4177c79c86a55019b0dccf636e6f33/images/bg.png) no-repeat top center;
        background-size: contain;
        width: 300px;
        height: 450px;
        margin: 0 auto;
        position: relative;
    }

    .dot-html .circle {
        display: inline-block;
        width: 10px;
        height: 10px;
        background: #000;
        border-radius: 50%;
    }

    .dot-html .active .circle {
        background: blue;
    }

    .dot-html .number {
        display: block;
        position: absolute;
        right: -10px;
    }

    .dot-html .line {
        background: #000;
        width: 3px;
        height: 100%;
        position: absolute;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
        display: none;
    }

    .dot-html .dot {
        display: block;
        cursor: pointer;
        padding: 10px;
        position: absolute;
        bottom: -18px;
        left: 50%;
        transform: translate(-50%, 0);
    }

    .dot-html .block-1-2 {
        width: 7.50%;
        height: 20.17%;
        position: absolute;
        top: 1.67%;
        right: 17.75%;
        transform: rotate(-23deg);
    }

    .dot-html .dot-1 {
        top: -14px;
        bottom: auto;
    }

    .dot-html .dot-1 .number {
        transform: rotate(23deg);
    }

    .dot-html .dot-2 .number {
        transform: rotate(23deg);
    }

    .dot-html .block-2-3 {
        width: 7.50%;
        height: 16.83%;
        position: absolute;
        transform: rotate(-5deg);
        top: 21.83%;
        right: 10.50%;
    }

    .dot-html .dot-3 .number {
        transform: rotate(5deg);
    }

    .dot-html .block-3-4 {
        width: 7.50%;
        height: 26.00%;
        position: absolute;
        transform: rotate(16deg);
        top: 39.00%;
        right: 14.50%;
    }

    .dot-html .dot-4 .number {
        transform: rotate(-16deg);
    }

    .dot-html .block-4-5 {
        width: 7.50%;
        height: 17.50%;
        position: absolute;
        transform: rotate(91deg);
        top: 56.83%;
        right: 33.75%;
    }

    .dot-html .dot-5 .number {
        transform: rotate(-91deg);
    }

    .dot-html .block-5-6 {
        width: 7.50%;
        height: 16.50%;
        position: absolute;
        transform: rotate(113deg);
        top: 53.67%;
        right: auto;
        left: 32.00%;
    }

    .dot-html .dot-6 .number {
        transform: rotate(-113deg);
    }

    .dot-html .block-6-7 {
        width: 7.50%;
        height: 20.00%;
        position: absolute;
        top: 38.17%;
        right: auto;
        left: 20.80%;
        transform: rotate(4deg);
    }

    .dot-html .dot-7 {
        top: -16px;
        bottom: auto;
    }

    .dot-html .dot-7 .number {
        transform: rotate(-2deg);
    }

    .dot-html .block-7-8 {
        width: 7.50%;
        height: 23.33%;
        position: absolute;
        transform: rotate(25deg);
        top: 16.33%;
        right: auto;
        left: 29.00%;
    }

    .dot-html .dot-8 {
        top: -16px;
        bottom: auto;
    }

    .dot-html .dot-8 .number {
        transform: rotate(-27deg);
    }

    .dot-html .block-8-9 {
        width: 7.50%;
        height: 20.83%;
        position: absolute;
        transform: rotate(54deg);
        top: 0.5%;
        right: auto;
        left: 49.75%;
    }

    .dot-html .dot-9 {
        top: -16px;
        bottom: auto;
    }

    .dot-html .dot-9 .number {
        transform: rotate(-54deg);
    }

    .dot-html .result {
        padding: 20px 0;
        text-align: center;
        display: none;
    }

    @media only screen and (max-width: 600px) {
        .dot-html .dot-container {
            width: 250px;
            height: 375px;
        }
    }

    #input-dot-8:checked~#input-dot-9:checked~div .line-8-9,
    #input-dot-7:checked~#input-dot-8:checked~div .line-7-8,
    #input-dot-6:checked~#input-dot-7:checked~div .line-6-7,
    #input-dot-5:checked~#input-dot-6:checked~div .line-5-6,
    #input-dot-4:checked~#input-dot-5:checked~div .line-4-5,
    #input-dot-3:checked~#input-dot-4:checked~div .line-3-4,
    #input-dot-2:checked~#input-dot-3:checked~div .line-2-3,
    #input-dot-1:checked~#input-dot-2:checked~div .line-1-2 {
        display: block;
    }

    #input-dot-9:checked~div .dot-9 .circle,
    #input-dot-8:checked~div .dot-8 .circle,
    #input-dot-7:checked~div .dot-7 .circle,
    #input-dot-6:checked~div .dot-6 .circle,
    #input-dot-5:checked~div .dot-5 .circle,
    #input-dot-4:checked~div .dot-4 .circle,
    #input-dot-3:checked~div .dot-3 .circle,
    #input-dot-2:checked~div .dot-2 .circle,
    #input-dot-1:checked~div .dot-1 .circle,
    .dot-html .dot:hover .circle {
        background: blue;
    }

    #input-dot-1:checked~#input-dot-2:checked~div .dot-1 .circle,
    #input-dot-2:checked~#input-dot-3:checked~div .dot-2 .circle,
    #input-dot-3:checked~#input-dot-4:checked~div .dot-3 .circle,
    #input-dot-4:checked~#input-dot-5:checked~div .dot-4 .circle,
    #input-dot-5:checked~#input-dot-6:checked~div .dot-5 .circle,
    #input-dot-6:checked~#input-dot-7:checked~div .dot-6 .circle,
    #input-dot-7:checked~#input-dot-8:checked~div .dot-7 .circle,
    #input-dot-8:checked~#input-dot-9:checked~div .dot-8 .circle {
        background: #000;
    }

    #input-dot-1:checked~#input-dot-2:checked~#input-dot-3:checked~#input-dot-4:checked~#input-dot-5:checked~#input-dot-6:checked~#input-dot-7:checked~#input-dot-8:checked~#input-dot-9:checked~.result {
        display: block;
    }
</style>

<div class="dot-html">
	<input id="input-dot-1" name="input-dot-1" type="radio" style="display:none">
	<input id="input-dot-2" name="input-dot-2" type="radio" style="display:none">
	<input id="input-dot-3" name="input-dot-3" type="radio" style="display:none">
	<input id="input-dot-4" name="input-dot-4" type="radio" style="display:none">
	<input id="input-dot-5" name="input-dot-5" type="radio" style="display:none">
	<input id="input-dot-6" name="input-dot-6" type="radio" style="display:none">
	<input id="input-dot-7" name="input-dot-7" type="radio" style="display:none">
	<input id="input-dot-8" name="input-dot-8" type="radio" style="display:none">
	<input id="input-dot-9" name="input-dot-9" type="radio" style="display:none">
    <div class="dot-container">
        <div class="block-8-9">
            <div class="line line-8-9"></div>
            <label for="input-dot-9" class="dot dot-9"><span class="circle"></span><span class="number">9</span></label>
        </div>
        <div class="block-7-8">
            <div class="line line-7-8"></div>
            <label for="input-dot-8" class="dot dot-8"><span class="circle"></span><span class="number">8</span></label>
        </div>
        <div class="block-6-7">
            <div class="line line-6-7"></div>
            <label for="input-dot-7" class="dot dot-7"><span class="circle"></span><span class="number">7</span></label>
        </div>
        <div class="block-5-6">
            <div class="line line-5-6"></div>
            <label for="input-dot-6" class="dot dot-6"><span class="number">6</span><span class="circle"></span></label>
        </div>
        <div class="block-4-5">
            <div class="line line-4-5"></div>
            <label for="input-dot-5" class="dot dot-5"><span class="number">5</span><span class="circle"></span></label>
        </div>
        <div class="block-3-4">
            <div class="line line-3-4"></div>
            <label for="input-dot-4" class="dot dot-4"><span class="number">4</span><span class="circle"></span></label>
        </div>
        <div class="block-2-3">
            <div class="line line-2-3"></div>
            <label for="input-dot-3" class="dot dot-3"><span class="number">3</span><span class="circle"></span></label>
        </div>
        <div class="block-1-2">
            <div class="line line-1-2"></div>
            <label for="input-dot-1" class="dot dot-1"><span class="number">1</span><span class="circle"></span></label>
            <label for="input-dot-2" class="dot dot-2"><span class="number">2</span><span class="circle"></span></label>
        </div>
    </div>
    <div class="result">
        <h2 style="padding-bottom:15px">Congratulations!</h2>
        <p>Here's your personal promo code GAMIFICATION for 15% OFF sitewide.</p>
    </div>
</div>

Здесь общая схема такая же, как и в AMP-версии, но вместо атрибутов AMP мы используем теги: связывающие теги label с тегами input с помощью атрибута «for». В этом атрибуте мы указываем id соответствующего input.

Верстка HTML-версии

Важное примечание: количество инпутов соответствует количеству точек на изображении.

Разбираемся со стилями

Стили помогают нам регулировать отображение игровых элементов. Вот как выглядят стили для отображения линий между точками:

Стили HTML для линий между точками

Если получатель кликает на точки 8 и 9, мы показываем сегмент 8-9, если на точки 7 и 8, мы показываем сегмент 7-8 и так далее. В качестве примера мы перечислим все точки, которые существуют в нашей игре.

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

Код стилей для точек в HTML-версии

И последнее, но не менее важное: стили, отвечающие за отображение блока с сообщением после того, как все точки будут закрашены:

Код появления финального сообщения

Фолбэк-версия

Для почтовых клиентов, не поддерживающих HTML5 и CSS3, необходимо создать дополнительный блок с кодом. Он будет иметь структуру, похожую на нашу механику, но без интерактивности. Клик по элементам приведет к переходу на веб-версию письма.

Продолжаем работать в блоке с интерактивным HTML, который мы сделали выше. Вставьте следующий код между тегами </style> и <div class="dot-html">:

<!--[if !mso]><!--><input type="checkbox" id="fallback_ctrl" class="fallback_ctrl" style="display:none !important;mso-hide:all;" checked>
<!--<![endif]-->
<!-- FALLBACK -->
<div id="fallback" class="fallback">
    <table width="100%">
        <tbody>
            <tr align="center">
                <td><a target="_blank" href="https://viewstripo.email/41a57244-a78a-40d8-88ee-f18848aba63b1711958538852?type=amphtml"><img src="https://zlnfb.stripocdn.email/content/guids/CABINET_c102d17d796d323a0ee84181252016915f4177c79c86a55019b0dccf636e6f33/images/bg.png" alt style="display: block;" width="258" height="450"></a></td>
            </tr>
        </tbody>
    </table>
</div><!-- /FALLBACK -->
<!--[if !mso]><!-->
<!-- INTERACTIVE ELEMENT -->
<div class="container" style="mso-hide:all;display:none;">

Куда вставить код фолбэка

Кроме того, вставьте этот код в конец кода:

</div><!-- /INTERACTIVE ELEMENT -->
<!--<![endif]-->

Куда вставить заключительную часть кода фолбэка

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

Ссылка на веб-версию

Важное примечание: подробнее о веб-версиях писем и о том, как их получить, читайте в нашей специальной статье.

Разбираемся со стилями

Чтобы задать внешний вид фолбэка, нам также нужно добавить стили. Добавьте этот фрагмент кода внутрь тега style (проще вставить его перед закрывающим тегом </style>):

    /* --- */
    @media screen and (-webkit-min-device-pixel-ratio: 0) {
        input.fallback_ctrl:checked~.container {
            display: block !important;
        }

        input.fallback_ctrl:checked~#fallback {
            display: none !important;
        }
    }

    [owa] .container {
        display: none !important;
    }

    [class~="x_container"] {
        display: none !important;
    }

    [id~="x_fallback"] {
        display: block !important;
    }

    @media screen and (max-width: 600px) {
        body[data-outlook-cycle] #fallback {
            display: block !important;
        }

        body[data-outlook-cycle] .container {
            display: none !important;
        }
    }

Место для вставки кода стилей фолбэка

Давайте рассмотрим код более подробно.

<!--[if !mso]><!--><input type="checkbox" id="fallback_ctrl" class="fallback_ctrl" style="display:none !important;mso-hide:all;" checked>

<!--<![endif]-->

Этот инпут необходим, чтобы показать или скрыть версию фолбэка с помощью стилей. Мы обернули его в комментарии <!--[if !mso]><!--> … <!--<![endif]-->, чтобы убедиться, что он скрыт в клиенте Outlook Desktop.

Тем временем <div id="fallback" class="fallback"></div> — это блок, содержащий весь макет нашего фолбэка. Он должен иметь простую структуру таблицы, подходящую для Outlook. В нашем примере это таблица в виде вкладок со ссылками, ведущими на веб-версию. Вы можете создать свою собственную версию, например, чтобы содержимое вкладок отображалось одно под другим без перехода к веб-версии. Главное — использовать разметку, понятную для Outlook.

Стили ниже отвечают за скрытие и отображение фолбэка. Если их убрать или закомментировать, фолбэк-версия будет видна, и вы сможете настроить ее дизайн под нужный вид. Не забудьте вернуть эти стили перед отправкой письма.

Стили фолбэка

Эти стили не имеют четких правил для каждого почтового клиента, но есть набор хаков, которые можно использовать для управления отображением:

  • стили, начинающиеся с [owa], используются для Outlook;
  • стили [class~="x_container"] необходимы для Outlook в случае, если [owa] не работает;
  • стили body[data-outlook-cycle] необходимы для работы с Outlook на мобильных устройствах iOS и Android;
  • mso-hide:all; используются для Outlook.com.

Полный код для интерактивной и фолбэк-версий

Здесь представлен код фолбэка игры, включая интерактивную HTML-часть и фолбэк-версию:

<style>
    .dot-html .dot-container {
        background: url(https://zlnfb.stripocdn.email/content/guids/CABINET_c102d17d796d323a0ee84181252016915f4177c79c86a55019b0dccf636e6f33/images/bg.png) no-repeat top center;
        background-size: contain;
        width: 300px;
        height: 450px;
        margin: 0 auto;
        position: relative;
    }

    .dot-html .circle {
        display: inline-block;
        width: 10px;
        height: 10px;
        background: #000;
        border-radius: 50%;
    }

    .dot-html .active .circle {
        background: blue;
    }

    .dot-html .number {
        display: block;
        position: absolute;
        right: -10px;
    }

    .dot-html .line {
        background: #000;
        width: 3px;
        height: 100%;
        position: absolute;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
        display: none;
    }

    .dot-html .dot {
        display: block;
        cursor: pointer;
        padding: 10px;
        position: absolute;
        bottom: -18px;
        left: 50%;
        transform: translate(-50%, 0);
    }

    .dot-html .block-1-2 {
        width: 7.50%;
        height: 20.17%;
        position: absolute;
        top: 1.67%;
        right: 17.75%;
        transform: rotate(-23deg);
    }

    .dot-html .dot-1 {
        top: -14px;
        bottom: auto;
    }

    .dot-html .dot-1 .number {
        transform: rotate(23deg);
    }

    .dot-html .dot-2 .number {
        transform: rotate(23deg);
    }

    .dot-html .block-2-3 {
        width: 7.50%;
        height: 16.83%;
        position: absolute;
        transform: rotate(-5deg);
        top: 21.83%;
        right: 10.50%;
    }

    .dot-html .dot-3 .number {
        transform: rotate(5deg);
    }

    .dot-html .block-3-4 {
        width: 7.50%;
        height: 26.00%;
        position: absolute;
        transform: rotate(16deg);
        top: 39.00%;
        right: 14.50%;
    }

    .dot-html .dot-4 .number {
        transform: rotate(-16deg);
    }

    .dot-html .block-4-5 {
        width: 7.50%;
        height: 17.50%;
        position: absolute;
        transform: rotate(91deg);
        top: 56.83%;
        right: 33.75%;
    }

    .dot-html .dot-5 .number {
        transform: rotate(-91deg);
    }

    .dot-html .block-5-6 {
        width: 7.50%;
        height: 16.50%;
        position: absolute;
        transform: rotate(113deg);
        top: 53.67%;
        right: auto;
        left: 32.00%;
    }

    .dot-html .dot-6 .number {
        transform: rotate(-113deg);
    }

    .dot-html .block-6-7 {
        width: 7.50%;
        height: 20.00%;
        position: absolute;
        top: 38.17%;
        right: auto;
        left: 20.80%;
        transform: rotate(4deg);
    }

    .dot-html .dot-7 {
        top: -16px;
        bottom: auto;
    }

    .dot-html .dot-7 .number {
        transform: rotate(-2deg);
    }

    .dot-html .block-7-8 {
        width: 7.50%;
        height: 23.33%;
        position: absolute;
        transform: rotate(25deg);
        top: 16.33%;
        right: auto;
        left: 29.00%;
    }

    .dot-html .dot-8 {
        top: -16px;
        bottom: auto;
    }

    .dot-html .dot-8 .number {
        transform: rotate(-27deg);
    }

    .dot-html .block-8-9 {
        width: 7.50%;
        height: 20.83%;
        position: absolute;
        transform: rotate(54deg);
        top: 0.5%;
        right: auto;
        left: 49.75%;
    }

    .dot-html .dot-9 {
        top: -16px;
        bottom: auto;
    }

    .dot-html .dot-9 .number {
        transform: rotate(-54deg);
    }

    .dot-html .result {
        padding: 20px 0;
        text-align: center;
        display: none;
    }

    @media only screen and (max-width: 600px) {
        .dot-html .dot-container {
            width: 250px;
            height: 375px;
        }
    }

    #input-dot-8:checked~#input-dot-9:checked~div .line-8-9,
    #input-dot-7:checked~#input-dot-8:checked~div .line-7-8,
    #input-dot-6:checked~#input-dot-7:checked~div .line-6-7,
    #input-dot-5:checked~#input-dot-6:checked~div .line-5-6,
    #input-dot-4:checked~#input-dot-5:checked~div .line-4-5,
    #input-dot-3:checked~#input-dot-4:checked~div .line-3-4,
    #input-dot-2:checked~#input-dot-3:checked~div .line-2-3,
    #input-dot-1:checked~#input-dot-2:checked~div .line-1-2 {
        display: block;
    }

    #input-dot-9:checked~div .dot-9 .circle,
    #input-dot-8:checked~div .dot-8 .circle,
    #input-dot-7:checked~div .dot-7 .circle,
    #input-dot-6:checked~div .dot-6 .circle,
    #input-dot-5:checked~div .dot-5 .circle,
    #input-dot-4:checked~div .dot-4 .circle,
    #input-dot-3:checked~div .dot-3 .circle,
    #input-dot-2:checked~div .dot-2 .circle,
    #input-dot-1:checked~div .dot-1 .circle,
    .dot-html .dot:hover .circle {
        background: blue;
    }

    #input-dot-1:checked~#input-dot-2:checked~div .dot-1 .circle,
    #input-dot-2:checked~#input-dot-3:checked~div .dot-2 .circle,
    #input-dot-3:checked~#input-dot-4:checked~div .dot-3 .circle,
    #input-dot-4:checked~#input-dot-5:checked~div .dot-4 .circle,
    #input-dot-5:checked~#input-dot-6:checked~div .dot-5 .circle,
    #input-dot-6:checked~#input-dot-7:checked~div .dot-6 .circle,
    #input-dot-7:checked~#input-dot-8:checked~div .dot-7 .circle,
    #input-dot-8:checked~#input-dot-9:checked~div .dot-8 .circle {
        background: #000;
    }

    #input-dot-1:checked~#input-dot-2:checked~#input-dot-3:checked~#input-dot-4:checked~#input-dot-5:checked~#input-dot-6:checked~#input-dot-7:checked~#input-dot-8:checked~#input-dot-9:checked~.result {
        display: block;
    }

    /* --- */
    @media screen and (-webkit-min-device-pixel-ratio: 0) {
        input.fallback_ctrl:checked~.container {
            display: block !important;
        }

        input.fallback_ctrl:checked~#fallback {
            display: none !important;
        }
    }

    [owa] .container {
        display: none !important;
    }

    [class~="x_container"] {
        display: none !important;
    }

    [id~="x_fallback"] {
        display: block !important;
    }

    @media screen and (max-width: 600px) {
        body[data-outlook-cycle] #fallback {
            display: block !important;
        }

        body[data-outlook-cycle] .container {
            display: none !important;
        }
    }
</style>
<!--[if !mso]><!--><input type="checkbox" id="fallback_ctrl" class="fallback_ctrl" style="display:none !important;mso-hide:all;" checked>
<!--<![endif]-->
<!-- FALLBACK -->
<div id="fallback" class="fallback">
    <table width="100%">
        <tbody>
            <tr align="center">
                <td><a target="_blank" href="https://viewstripo.email/c29e42f1-be3f-4496-baae-104fe5d89bb51719820023314?type=amphtml"><img src="https://zlnfb.stripocdn.email/content/guids/CABINET_c102d17d796d323a0ee84181252016915f4177c79c86a55019b0dccf636e6f33/images/bg.png" alt style="display: block;" width="258" height="450"></a></td>
            </tr>
        </tbody>
    </table>
</div><!-- /FALLBACK -->
<!--[if !mso]><!-->
<!-- INTERACTIVE ELEMENT -->
<div class="container" style="mso-hide:all;display:none;">
    <div class="dot-html"><input id="input-dot-1" name="input-dot-1" type="radio" style="display:none"><input id="input-dot-2" name="input-dot-2" type="radio" style="display:none"><input id="input-dot-3" name="input-dot-3" type="radio" style="display:none"><input id="input-dot-4" name="input-dot-4" type="radio" style="display:none"><input id="input-dot-5" name="input-dot-5" type="radio" style="display:none"><input id="input-dot-6" name="input-dot-6" type="radio" style="display:none"><input id="input-dot-7" name="input-dot-7" type="radio" style="display:none"><input id="input-dot-8" name="input-dot-8" type="radio" style="display:none"><input id="input-dot-9" name="input-dot-9" type="radio" style="display:none">
        <div class="dot-container">
            <div class="block-8-9">
                <div class="line line-8-9"></div><label for="input-dot-9" class="dot dot-9"><span class="circle"></span><span class="number">9</span></label>
            </div>
            <div class="block-7-8">
                <div class="line line-7-8"></div><label for="input-dot-8" class="dot dot-8"><span class="circle"></span><span class="number">8</span></label>
            </div>
            <div class="block-6-7">
                <div class="line line-6-7"></div><label for="input-dot-7" class="dot dot-7"><span class="circle"></span><span class="number">7</span></label>
            </div>
            <div class="block-5-6">
                <div class="line line-5-6"></div><label for="input-dot-6" class="dot dot-6"><span class="number">6</span><span class="circle"></span></label>
            </div>
            <div class="block-4-5">
                <div class="line line-4-5"></div><label for="input-dot-5" class="dot dot-5"><span class="number">5</span><span class="circle"></span></label>
            </div>
            <div class="block-3-4">
                <div class="line line-3-4"></div><label for="input-dot-4" class="dot dot-4"><span class="number">4</span><span class="circle"></span></label>
            </div>
            <div class="block-2-3">
                <div class="line line-2-3"></div><label for="input-dot-3" class="dot dot-3"><span class="number">3</span><span class="circle"></span></label>
            </div>
            <div class="block-1-2">
                <div class="line line-1-2"></div><label for="input-dot-1" class="dot dot-1"><span class="number">1</span><span class="circle"></span></label><label for="input-dot-2" class="dot dot-2"><span class="number">2</span><span class="circle"></span></label>
            </div>
        </div>
        <div class="result">
            <h2 style="padding-bottom:15px">Congratulations!</h2>
            <p>Here's your personal promo code GAMIFICATION for 15% OFF sitewide.</p>
        </div>
    </div>
</div><!-- /INTERACTIVE ELEMENT -->
<!--<![endif]-->

Эта часть кода предназначена только для проверки и для того, чтобы убедиться, что вы не допустили ошибок на предыдущих этапах нашего гайда. Если что-то не работает так, как задумано, сравните свой код с этим полным примером, чтобы понять, в чем дело.

В завершение

На первый взгляд, игра может показаться довольно простой, но ее прелесть в том, что вы ограничены только своей фантазией в том, какой рисунок можно придумать. Сложность и увлекательность игры зависит только от того, насколько сильно вы захотите сделать ее такой, создавая различные версии игры «Соедините точки».

Надеемся, что этот гайд станет надежной опорой для наполнения ваших писем интерактивностью и новыми механиками.

Создавайте эксклюзивные письма с помощью Stripo
Была ли статья полезна?
Tell us your thoughts
Спасибо за ваш отзыв!
0 комментариев
Тип
Индустрия
Сезоны
Интеграции
Редактор Stripo
Упростите процесс создания писем.
Плагин Stripo
Интегрируйте Drag-n-Drop редактор Stripo в свое веб-приложение.
Заказать шаблон
Наша команда может разработать и сверстать его для вас. Просто заполните бриф, и мы свяжемся с вами в ближайшее время.

Редактор Stripo

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

Плагин Stripo

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