Главное Авторские колонки Вакансии Вопросы
913 14 В избр. Сохранено
Авторизуйтесь
Вход с паролем

Как сверстать интерактивные вкладки в email-письме

Как сверстать интерактивные вкладки, которые будут работать в почтовых программах iOS, Android и популярных веб-приложениях.
Мнение автора может не совпадать с мнением редакции

W89MMoPig414xEBFG_WQVT8mETHKh54bxNpykK7p

В нашем блоге мы уже неоднократно рассказывали о создании интерактивных email-рассылок с помощью CSS и HTML. Сегодня мы представляем вашему вниманию адаптированный перевод заметки Джастина Ку о том, как сверстать интерактивные вкладки, которые будут работать в почтовых программах iOS, Android и популярных веб-приложениях.

Радиокнопки, ярлыки и псевдокласс :checked

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

Как правило в подобных примерах используется комбинация радиокнопки, ярлыков и псевдокласса CSS3 :checked. Вот как это выглядит:

CSIpG1RQIQkmk8UUgk4agVhvTBsdA5pGF_9syNPT

А вот так выглядит код:

<style>/* hide radio element */.myradio { display:none; height:0px; visibility:hidden;}.mybox { width:100px; height:50px; background-color: #eeeeee; display:none; padding:5px;}/* change tab to bold */.myradio:checked + label { font-weight: bold;} /* show content */#radio1:checked ~ .box1,#radio2:checked ~ .box2{ display:block;}</style><input name="myradio" type=radio id="radio1" class="myradio" checked><label for="radio1">Tab 1</label> | <input name="myradio" type=radio id="radio2" class="myradio"><label for="radio2">Tab 2</label><div class="mybox box1">Box 1</div><div class="mybox box2">Box 2</div>

Заголовки вкладок «обернуты» ярлыками и размещены под связанным радиоэлементом, который скрыт с помощью стилей. Далее заголовок связывается с радиоэлементом с помощью атрибута for — в итоге клик по заголовку активирует радиоэлемент с id, совпадающим со значением атрибута for.

Затем использование псевдокласса :checked и родственные селекторов adjacent (+) и general (~) можно выборочно выделять жирным шрифтом название и отображать связанный контент вкладки.

Эта простая техника работает на мобильных клиентах и webkit-based почтовых програмаах, таких как приложения в iOS и Android. Однако для отображения в веб-клиентах нужно еще поработать.

Интерактивные вкладки в вебе

В вебе проблемой является невозможность использования определенных CSS-стилей. Например, Gmail вырезает классы и id, Outlook.com не поддерживает псевдокласс :checked, а Yahoo! Mail вырезает селектор (~) и при рендеринге переименовывает id и классы, делая атрибут for бесполезным.

Реализовать поддержку в Yahoo! Mail и Gmail можно с помощью следующих трюков:

  1. Радиоэлемент и контент вкладки нужно поместить внутрь ярлыка. Это позволит отказаться от использования атрибута for — клик на ярлыке автоматически будет активировать вложенный в него радиоэлемент.
  2. Ярлыки, инпуты и контент будут вкладываться на манер матрешки. Это позволит использовать селектор (+), который требует, чтобы активированные и целевые элементы были связаны друг с другом — в нашем случае это радиоинпут и обертка span.
<label><input type=radio name="tab" id="tab1" checked><span><div class="title1">Tab 1</div> <!-- NESTED TAB 2 --> <label><input type=radio name="tab" id="tab2"> <span><div class="title2">Tab 2</div> <!-- NESTED TAB 3 --> <label><input type=radio name="tab" id="tab3"> <span><div class="title3">Tab 3</div> <div class="content3"> Tab 3 Content </div></span> </label> <!-- /NESTED TAB 3 --> <div class="content2"> Tab 2 Content </div></span> </label> <!-- /NESTED TAB 2 --><div class="content1">Tab 1 Content</div></span></label>
  1. Наконец, мы будем использовать технику lang (ее мы описывали ранее), которая позволит использовать стили в веб-клиенте Gmail.

Работа с неподдерживаемыми клиентами

Также нам надо убедиться в том, что пользователи неподдерживаемых почтовых программ не будут видеть сломанное письмо. Для того, чтобы этого добиться, можно воспользоваться двумя стратегиями. Самый простой путь — полностью скрыть все, что связано с вкладками (это потребует, в частности, оборачивания контента в условные комментарии Outlook — вы же не думали, что это сработает в десктоп-клиенте Outlook?)

Одним из способов такого скрытия для клиентов, которые не поддерживают псевдокласс :checked, заключается в оборачивании контента вкладок в div-контейнер, которые уже будет скрываться. Затем выбранный радиоинпут размещается перед div-элементом, а в блок стилей добавляется селектор, который с помощью :checked отображает div-контейнер, если селектор совпадает:

<style>.tabcheck:checked + div{ display:block !important; max-height: none !important; height: auto !important;}</style><input type=radio class="tabcheck" style="display:none !important;" checked><div style="height:0px;max-height:0px;overflow:hidden;">TABBED CONTENT</div>

Полное скрытие контента — не идеальный выход из положения. Так что можно еще и извлечь контент первой вкладки и отобразить его по умолчанию, однако завернуть его в div фиксированной высоты с наложением на скрытый контент. Если же активирована вторая вкладка, то контент первой вкладки все еще отображается, но невидим, поскольку вытесняется за пределы видимой части ограниченного по высоте div.

Еще один выход — полностью скрыть вкладки и отображать вместо них отобразить не-интерактивных шаблон (пример описан в этом тексте).

Под спойлером расположен полный код примера (поработать с ним можно на Codepen):

<head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>Interactive Tabs for Email</title><style>* {  font-family: Helvetica, sans-serif;  margin:0; padding:0;}body { -webkit-text-size-adjust:100%; }.tab, .tabcheck { display: none;}.tabcheck { height:0px; visibility:hidden;} .title1,.title2,.title3 { background-color:#ffffff; float: left; padding:15px 20px 15px 20px; border: 1px solid #888888; border-bottom: 0px; cursor: pointer; border-radius: 5px 5px 0px 0px;}.tabcheck:checked + #container { height: 363px !important; max-height: 363px !important;}.tabcheck:checked + div, #tab2:checked + span .content2,#tab3:checked + span .content3{ display:block !important; max-height: none !important; height: auto !important;}#tab1:checked + span .title1,#tab2:checked + span .title2,#tab3:checked + span .title3 { background-color:#bbbbbb;}/* GMAIL [lang] fix*/.gfix{}* [lang=x-title1],* [lang=x-title2],* [lang=x-title3]{ background-color:#ffffff; float: left; padding:15px 20px 15px 20px; border: 1px solid #888888; border-bottom: 0px; cursor: pointer; border-radius: 5px 5px 0px 0px;}* [lang=x-tabcheck]:checked + [lang=x-container] { height: 363px !important; max-height: 363px !important;}* [lang=x-tabcheck]:checked + div, * [lang=x-tab2]:checked + span [lang=x-content2],* [lang=x-tab3]:checked + span [lang=x-content3]{ display:block !important; max-height: none !important; height: auto !important;}* [lang=x-tab1]:checked + span [lang=x-title1],* [lang=x-tab2]:checked + span [lang=x-title2],* [lang=x-tab3]:checked + span [lang=x-title3]{ background-color:#bbbbbb;}</style></head><body bgcolor="#ffcc00"><table width="100%" height="100%"> <tr> <td></td> <td bgcolor="#ffcc00"> <div class="content"> <table> <tr> <td><BR><form><!--[if !mso]><!-- --><input type=radio class="tabcheck" lang="x-tabcheck" style="display:none !important;" checked><!--<![endif]--><div id="container" lang="x-container" style="width:500px;height:310px;max-height:310px;overflow:hidden;"><!--[if !mso]><!-- --><input type=radio class="tabcheck" lang="x-tabcheck" style="display:none !important;" checked><div style="height:0px;max-height:0px;overflow:hidden;"><label><input type=radio name="tab" class="tab" lang="x-tab1" id="tab1" style="display:none !important;" checked><span><div class="title1" lang="x-title1" >Tab 1</div> <!-- NESTED TAB 2 --> <label><input type=radio name="tab" class="tab" lang="x-tab2" id="tab2" style="display:none !important;"><span><div class="title2" lang="x-title2">Tab 2</div> <!-- NESTED TAB 3 --> <label><input type=radio name="tab" class="tab" lang="x-tab3" id="tab3" style="display:none !important;"><span><div class="title3" lang="x-title3">Tab 3</div> <div class="content3" lang="x-content3" style="height:0px;max-height:0px;overflow:hidden;clear:left;"> <table cellpadding="0" cellspacing="0"> <tr> <td colspan="2" height="150" width="500" bgcolor="#bbbbbb" valign=center align=center style="font-size:50px;color:#555555;"><b>Tab 3</b></td> </tr><tr> <td width="250" height="170" valign="top" style="background: #777777; font-family: Helvetica; font-size: 14px; line-height: 100%; color: #ffffff;"><div style="padding:20px;"> <H2>Title 3A</H2> <p>The quick, brown fox jumps over a lazy dog. <BR><BR> <a href="#" style="color: #BDD4FC;">View Deal</a> </p> </div></td> <td width="250" height="170" valign="top" style="background: #555555; font-family: Helvetica; font-size: 14px; line-height: 100%; color: #ffffff;"><div style="padding:20px;"> <h2>Title 3B</h2> <p>The quick, brown fox jumps over a lazy dog. <BR><BR> <a href="#" style="color: #BDD4FC;">View Deal</a> </p> </div></td> </tr> </table> </div></span> </label> <!-- END NESTED TAB 3 --> <div class="content2" lang="x-content2" style="height:0px;max-height:0px;overflow:hidden;clear:left;"> <table cellpadding="0" cellspacing="0"> <tr> <td colspan="2" height="150" width="500" bgcolor="#bbbbbb" valign=center align=center style="font-size:50px;color:#555555;"><b>Tab 2</b></td> </tr> <tr> <td width="250" height="170" valign="top" style="background: #777777; font-family: Helvetica; font-size: 14px; line-height: 100%; color: #ffffff;"><div style="padding:20px;"> <H2>Title 2A</H2> <p>The quick, brown fox jumps over a lazy dog. <BR><BR> <a href="#" style="color: #BDD4FC;">View Deal</a> </p> </div></td> <td width="250" height="170" valign="top" style="background: #555555; font-family: Helvetica; font-size: 14px; line-height: 100%; color: #ffffff;"><div style="padding:20px;"> <h2>Title 2B</h2> <p>The quick, brown fox jumps over a lazy dog. <BR><BR> <a href="#" style="color: #BDD4FC;">View Deal</a> </p> </div></td> </tr> </table> </div> </span> </label> <!-- END NESTED TAB 2 --> <!-- TAB 1 Content originally here --></span></label></div><!--<![endif]--><!-- TAB 1 Content moved outside nested labels for fallback for non supported clients: Outlook.com/Outlook --><table cellpadding="0" cellspacing="0"> <tr> <td colspan="2" height="150" width="500" bgcolor="#bbbbbb" valign=center align=center style="font-size:50px;color:#555555;"><b>Tab 1</b></td> </tr> <tr> <td width="250" height="170" valign="top" style="background: #777777; font-family: Helvetica; font-size: 14px; line-height: 100%; color: #ffffff;"><div style="padding:20px;"> <H2>Title 1A</H2> <p>The quick, brown fox jumps over a lazy dog. <BR><BR> <a href="#" style="color: #BDD4FC;">View Deal</a> </p> </div></td> <td width="250" height="170" valign="top" style="background: #555555; font-family: Helvetica; font-size: 14px; line-height: 100%; color: #ffffff;"><div style="padding:20px;"> <h2>Title 1B</h2> <p>The quick, brown fox jumps over a lazy dog.<BR><BR> <a href="#" style="color: #BDD4FC;">View Deal</a> </p> </div></td> </tr></table></div></form> </td> </tr> </table> </div> </td> <td></td> </tr></table></body></html>
0
В избр. Сохранено
Авторизуйтесь
Вход с паролем
Комментарии
Магазин Таобао
Cайт (движок) с товарами Taobao на русском языке
Магазин Таобао
Скоро письма будут приходить в виде сайта :)
Ответить
Tucanus
3D-печать иначе
Григорий 10016
http://habrahabr.ru/company/pechkin/blog/265409/
Господа, самим не стыдно? Хотя бы рерайт проводите.
Ответить
BrandSecurity
Защищаем бренды в Интернете
Alexander Lashkov
Зачем? И полагаю, что господам не стыдно, поскольку (о ужас), так делает половина спарка. Например:
http://spark.ru/startup/yagla - http://megamozg.ru/company/yagla/

http://spark.ru/startup/callbackkiller/blog - http://megamozg.ru/company/callbackkiller/

http://spark.ru/startup/logo/blog - http://megamozg.ru/company/logomachine/

Не знаю, Григорий, как ты будешь с этим знанием дальше жить.
Ответить
Tucanus
3D-печать иначе
Григорий 10016
Смешно после такого читать от вас статьи, где вы учите, как правильно надо работать с негативом в комментариях.
Ответить
Розанов Александр
Обвинять половину Spark не выход.
Ответить
BrandSecurity
Защищаем бренды в Интернете
Alexander Lashkov
В данный момент я не работаю с негативом, а высказываю свое мнение. С точки зрения бизнеса компании не будут писать отдельный контент под спарк, если есть возможность публиковать и сюда и не сюда. Пока в правилах сайта нет подобных запретов, когда они появятся, тогда конечно да, нужно будет видоизменять контент.
Ответить
BrandSecurity
Защищаем бренды в Интернете
Alexander Lashkov
Не выход считать, что закрывать глаза на уровень развития ресурса не стоит — когда спарк будет давать больше отдачи чем Хабр, я буду первый, кто все проекты перенесет только сюда, ибо на ресурсах ТМ глупостей на порядок больше.
Ответить
SMS Aero
Сервис SMS-маркетинга и SMS-информирования
SMS Aero
Спасибо за статью. Возник такой вопрос: для чего вы бы использовали вкладки в письмах? По Email, как и по SMS информируют клиентов о чем-то срочном/важном/интересном для них. И получатель просматривает текст всего письма за 5-7 секунд. Велика вероятность, что он вообще не увидит эти вкладки и не прочтет то, что в них скрыто. Писать в них не самую важную информацию? Тогда для чего она вообще нужна в письме?
Ответить
BrandSecurity
Защищаем бренды в Интернете
Alexander Lashkov
Вы слишком серьезно подходите к вопросу, это явный эксперимент, который показывает возможности такого инструмента, как email. Никто и нигде не предлагает использовать это на ежедневной основе, иногда это может быть полезно в ситуациях типа вот этой http://spark.ru/startup/pechkin-mail/blog/10787/kak-pashalki-v-email-pomogli-kompanii-privlech-vnimanie-k-svoej-konferentsii
Ответить
SMS Aero
Сервис SMS-маркетинга и SMS-информирования
SMS Aero
Речь не о ежедневных рассылках, конечно же. Хотелось узнать мнение автора о возможностях инструмента вообще. Примеры интересные, спасибо.
Ответить
Кораблев Егор
Вкладки в письмах - мне кажется ненужный инструмент. И так сложно сверстать письмо, чтобы оно одинаково отображалось в Outlook и The Bat.
Ответить
BrandSecurity
Защищаем бренды в Интернете
Alexander Lashkov
Узконаправленный инструмент — например, для рассылок писем от автоматизированных систем со всякой статистикой (например, по серверам), можно размещать данные во вкладках, чтобы не надо было скроллить несколько экранов.

Соответственно, в этом случае можно прямо указывать, что работать это будет в одном конкретном клиенте. В корпоративных системах такое не редкость
Ответить
Кораблев Егор
А, ну для статистики действительно может быть полезно.
Ответить
Выбрать файл
Блог проекта
Расскажите историю о создании или развитии проекта, поиске команды, проблемах и решениях
Написать
Личный блог
Продвигайте свои услуги или личный бренд через интересные кейсы и статьи
Написать

Spark использует cookie-файлы. С их помощью мы улучшаем работу нашего сайта и ваше взаимодействие с ним.