La technique des « Fab Four » pour créer des e‑mails responsive sans media queries

Je pense avoir trouvé une nouvelle façon de créer des e‑mails responsive, sans media queries. La solution implique la fonction CSS calc(), et les trois propriétés width, min-width ou max-width.

Ou comme je me plais à les appeler une fois toutes réunies : les « Fab Four » (en CSS).

calc() & width & min-width & max-width.

Lire la suite

Snowball Surprise: Shaking the Email

Un exemple d’animation un peu kitsch mais amusante chez FreshInbox : comment « secouer » un e-mail en ajoutant une animation sur le conteneur principal d’un e‑mail.

Gmail App on Android tries to shrink your email with ‘munged’ classes

Le mois dernier, le blog Mosaico a fait un travail formidable de recherche dans le code source d’Android. L’auteur a découvert ce qui supposément peut être associé au comportement de Gmail forçant le redimensionnement d’e-mails.

Dans certains cas, Gmail va ajouter une classe .munged (en anglais selon Wikipedia, « une série de changements potentiellement destructifs ou irrévocables ») à toutes les <table> et <td>. Cette classe va appliquer un width:auto !important;, causant les dommages qu’on peut imaginer.

Super Mail Forward, cinq mois après

J’ai publié une traduction en anglais de mon retour sur la création de Super Mail Forward, un e-mail transférable évolutif. Cinq mois après, il y a deux changements principaux.

AOL a corrigé le bug de remplacement des images en background dans une balise <style>. J’ai donc trouvé une autre bidouille pour activer des styles sur AOL. Ou plus précisément, pour ne pas que des styles s’activent sur AOL. En fait, une balise <style> contenant une image de fond à l’URL non supportée (par exemple background:url('#');) sera totalement supprimée. Dans l’exemple suivant, ces styles s’appliqueront donc partout (ou presque), sauf sur AOL.

<style type="text/css">
   .step1 { background:url('#'); }
   .step1 .W { background:#fff!important; }
   .step1 .X { background:#f8d81f!important; }
   .step1 .Y { background:#d89f37!important; }
   .step1 .Z { background:#000!important; }
</style>

Microsoft a commencé à remplacer Outlook.com par le même webmail qu’Office 365 (aussi appelé Outlook Web App). Ce webmail ne supporte pas les sélecteurs d’attributs. Pour cibler des styles uniquement sur ce webmail, on peut donc écrire le sélecteur suivant…

<style type="text/css">
   [owa] .toto { … }
</style>

…qui sera interprété comme :

<style type="text/css">
   .rps_123a .x_toto { … }
</style>

Photoshop, copier-coller et les caractères invisibles ETX

Code and Send a publié un court article très intéressant sur les caractères invisibles ETX qui peuvent apparaître quand on copie-colle du texte depuis Photoshop. Ce caractère est ajouté par Photoshop lorsqu’on fait un saut de ligne avec MAJ+Entrée. Pour éviter ça, Code and Send a créé Detergent.io, un petit outil en ligne pour nettoyer du texte copié depuis Photoshop ou Word et destiné à être intégré dans un e‑mail.

Outlook.com ne préfixe pas les classes correspondant à des noms de balises

Comme la plupart des webmails, Outlook.com ajoute un préfixe aux noms de classes de nos e‑mails. Ainsi, une classe test sera transformée en ecxtest. Il y a quelques mois, j’avais remarqué cependant que ce préfixage ne s’appliquait pas sur certains noms de classes, comme par exemple button, menu, label ou nav.

Dans la troisième édition de son excellentissime Email Development Newsletter, Julie Ng évoque également ce bug qu’elle a rencontré en utilisant des classes head, header ou footer. Il n’en a pas fallu plus pour que je fasse le rapprochement et comprenne ce qu’il se passe. Tous ces mots-clés ne sont pas des noms pris au hasard, mais des noms de balises HTML.

Ni une, ni deux, je suis allé récupéré la liste des éléments HTML sur MDN, et j’ai envoyé le test suivant sur Outlook.com.

<style type="text/css">
	.html, .base, .head, .link, .meta, .style, .title, .address, .article, .body, .footer, .header, .h1, .h2, .h3, .h4, .h5, .h6, .hgroup, .nav, .section, .blockquote, .dd, .div, .dl, .dt, .figcaption, .figure, .hr, .li, .main, .ol, .p, .pre, .ul, .a, .abbr, .b, .bdi, .bdo, .br, .cite, .code, .data, .dfn, .em, .i, .kbd, .mark, .q, .rp, .rt, .ruby, .s, .samp, .small, .span, .strong, .sub, .sup, .time, .u, .var, .wbr, .area, .audio, .img, .map, .track, .video, .embed, .iframe, .object, .param, .source, .canvas, .noscript, .script, .del, .ins, .caption, .col, .colgroup, .table, .tbody, .td, .tfoot, .th, .thead, .tr, .button, .datalist, .fieldset, .form, .input, .keygen, .label, .legend, .meter, .optgroup, .option, .output, .progress, .select, .textarea, .details, .dialog, .menu, .menuitem, .summary, .content, .decorator, .element, .shadow, .template, .acronym, .applet, .basefont, .big, .blink, .center, .dir, .frame, .frameset, .isindex, .listing, .noembed, .plaintext, .spacer, .strike, .tt, .xmp {
		padding:1em 1.5em;
		color:#fff;
		background:#2ecc40;
	}
</style>
<div class="html base head link meta style title address article body footer header h1 h2 h3 h4 h5 h6 hgroup nav section blockquote dd div dl dt figcaption figure hr li main ol p pre ul a abbr b bdi bdo br cite code data dfn em i kbd mark q rp rt ruby s samp small span strong sub sup time u var wbr area audio img map track video embed iframe object param source canvas noscript script del ins caption col colgroup table tbody td tfoot th thead tr button datalist fieldset form input keygen label legend meter optgroup option output progress select textarea details dialog menu menuitem summary content decorator element shadow template acronym applet basefont big blink center dir frame frameset isindex listing noembed plaintext spacer strike tt xmp"></div>

Ce code est transformé par le code suivant :

<style type="text/css">
	.ExternalClass .ecxhtml, .ExternalClass .ecxbase, .ExternalClass .ecxhead, .ExternalClass .ecxlink, .ExternalClass .ecxmeta, .ExternalClass .ecxstyle, .ExternalClass .ecxtitle, .ExternalClass .ecxaddress, .ExternalClass .ecxarticle, .ExternalClass .ecxbody, .ExternalClass .ecxfooter, .ExternalClass .ecxheader, .ExternalClass .ecxh1, .ExternalClass .ecxh2, .ExternalClass .ecxh3, .ExternalClass .ecxh4, .ExternalClass .ecxh5, .ExternalClass .ecxh6, .ExternalClass .ecxhgroup, .ExternalClass .ecxnav, .ExternalClass .ecxsection, .ExternalClass .ecxblockquote, .ExternalClass .ecxdd, .ExternalClass .ecxdiv, .ExternalClass .ecxdl, .ExternalClass .ecxdt, .ExternalClass .ecxfigcaption, .ExternalClass .ecxfigure, .ExternalClass .ecxhr, .ExternalClass .ecxli, .ExternalClass .ecxmain, .ExternalClass .ecxol, .ExternalClass .ecxp, .ExternalClass .ecxpre, .ExternalClass .ecxul, .ExternalClass .ecxa, .ExternalClass .ecxabbr, .ExternalClass .ecxb, .ExternalClass .ecxbdi, .ExternalClass .ecxbdo, .ExternalClass .ecxbr, .ExternalClass .ecxcite, .ExternalClass .ecxcode, .ExternalClass .ecxdata, .ExternalClass .ecxdfn, .ExternalClass .ecxem, .ExternalClass .ecxi, .ExternalClass .ecxkbd, .ExternalClass .ecxmark, .ExternalClass .ecxq, .ExternalClass .ecxrp, .ExternalClass .ecxrt, .ExternalClass .ecxruby, .ExternalClass .ecxs, .ExternalClass .ecxsamp, .ExternalClass .ecxsmall, .ExternalClass .ecxspan, .ExternalClass .ecxstrong, .ExternalClass .ecxsub, .ExternalClass .ecxsup, .ExternalClass .ecxtime, .ExternalClass .ecxu, .ExternalClass .ecxvar, .ExternalClass .ecxwbr, .ExternalClass .ecxarea, .ExternalClass .ecxaudio, .ExternalClass .ecximg, .ExternalClass .ecxmap, .ExternalClass .ecxtrack, .ExternalClass .ecxvideo, .ExternalClass .ecxembed, .ExternalClass .ecxiframe, .ExternalClass .ecxobject, .ExternalClass .ecxparam, .ExternalClass .ecxsource, .ExternalClass .ecxcanvas, .ExternalClass .ecxnoscript, .ExternalClass .ecxscript, .ExternalClass .ecxdel, .ExternalClass .ecxins, .ExternalClass .ecxcaption, .ExternalClass .ecxcol, .ExternalClass .ecxcolgroup, .ExternalClass .ecxtable, .ExternalClass .ecxtbody, .ExternalClass .ecxtd, .ExternalClass .ecxtfoot, .ExternalClass .ecxth, .ExternalClass .ecxthead, .ExternalClass .ecxtr, .ExternalClass .ecxbutton, .ExternalClass .ecxdatalist, .ExternalClass .ecxfieldset, .ExternalClass .ecxform, .ExternalClass .ecxinput, .ExternalClass .ecxkeygen, .ExternalClass .ecxlabel, .ExternalClass .ecxlegend, .ExternalClass .ecxmeter, .ExternalClass .ecxoptgroup, .ExternalClass .ecxoption, .ExternalClass .ecxoutput, .ExternalClass .ecxprogress, .ExternalClass .ecxselect, .ExternalClass .ecxtextarea, .ExternalClass .ecxdetails, .ExternalClass .ecxdialog, .ExternalClass .ecxmenu, .ExternalClass .ecxmenuitem, .ExternalClass .ecxsummary, .ExternalClass .ecxcontent, .ExternalClass .ecxdecorator, .ExternalClass .ecxelement, .ExternalClass .ecxshadow, .ExternalClass .ecxtemplate, .ExternalClass .ecxacronym, .ExternalClass .ecxapplet, .ExternalClass .ecxbasefont, .ExternalClass .ecxbig, .ExternalClass .ecxblink, .ExternalClass .ecxcenter, .ExternalClass .ecxdir, .ExternalClass .ecxframe, .ExternalClass .ecxframeset, .ExternalClass .ecxisindex, .ExternalClass .ecxlisting, .ExternalClass .ecxnoembed, .ExternalClass .ecxplaintext, .ExternalClass .ecxspacer, .ExternalClass .ecxtt, .ExternalClass .ecxxmp {
		padding:1em 1.5em;
		color:#fff;
		background:#2ecc40;
	}
</style>
<div class="html base head link meta style title address article body footer header h1 h2 h3 h4 h5 h6 hgroup nav section blockquote dd div dl dt figcaption figure hr li ecxmain ol p pre ul a abbr b bdi bdo br cite code ecxdata dfn em i kbd mark q rp rt ruby s samp small span strong sub sup time u var wbr area audio img map track video embed iframe object param source canvas noscript script del ins caption col colgroup table tbody td tfoot th thead tr button datalist fieldset form input keygen label legend meter optgroup option output progress select textarea details ecxdialog menu ecxmenuitem summary ecxcontent ecxdecorator ecxelement ecxshadow ecxtemplate acronym applet basefont big blink center dir frame frameset isindex listing ecxnoembed plaintext spacer strike tt xmp"></div>

Tous les sélecteurs CSS sont bien préfixés par .ExternalClass .ecx. Par contre, les noms de classe dans le code HTML ne sont eux pas préfixés par ecx, rendant le sélecteur précédent caduque. Seuls quelques noms d’éléments HTML semblent échapper à ce bug (comme main, data, dialog, menuitem, content, decorator, element, shadow, template and noembed).

Par précaution, il est donc plus prudent de ne jamais utiliser de nom de balise HTML comme nom de classe.

Un e-mail interactif de PRET A MANGER

Un e-mail interactif par PRET A MANGERVu sur Twitter : un e-mail interactif avec des smoothies par PRET A MANGER. J’adore le rendu avec les animations (faites en sprites). Mais quel dommage que le tout soit déclenché par une media query utilisant -webkit-min-device-pixel-ratio, ne fonctionnant alors que sur Chrome, Safari ou Opera.

Outlook pour iOS et Android

La semaine dernière, Microsoft a mis à jour son application Outlook pour iOS et Android, incluant des fonctions de calendrier et tuant au passage l’application Sunrise. Mais la vraie nouveauté, de mon point de vue, est que l’application iOS est actuellement neuvième des applications gratuites les plus téléchargées sur l’App Store (contre trente-cinquième pour Gmail).

Ne sous-estimons pas les applications mail tierces sur mobile.

Orange remplace le mot « overflow » par « java‑script »

Le webmail desktop d’Orange remplace le mot « overflow » par « java‑script ». Pas juste la propriété overflow en CSS. Mais carrément le mot « overflow », peu importe où vous l’employez dans un e‑mail.

Ainsi le code suivant :

<style>
	h1 { overflow:auto; }
</style>
<div style="overflow:hidden;">
	<h1 style="overflow:visible;">
		Un e‑mail qui parle d'overflow.
	</h1>
</div>

…est transformé en :

<style>
	h1 { java-script:auto; }
</style>
<div style="java-script:hidden;">
	<h1 style="java-script:visible;">
		Un e‑mail qui parle d'java-script.
	</h1>
</div>

Cela concerne uniquement le webmail desktop d’Orange (et pas sur l’application iOS ou le webmail mobile par exemple). Et cela se produit même lorsque « overflow » est inclus dans un autre mot.

Ça doit être très perturbant de lire des e‑mails de Stack Overflow sur le webmail d’Orange.

Supprimer les marges de l’application mail d’Android 4.4

James White a fait des recherches poussées pour comprendre d’où venaient des marges ajoutées autour du corps d’un e-mail sur l’application mail par défaut d’Android 4.4.

Résultat : l’application englobe chaque e-mail d’un <div style="margin: 16px 0;"> et ajoute un margin variable sur le <body> calculé selon la densité de pixels de l’appareil utilisé.

Pour annuler tout ça, James suggère d’ajouter les styles suivants :

body { margin:0 !important; }
div[style*="margin: 16px 0"] { margin:0 !important; }