试想一下,你在夜深人静的时候,准备睡前查看一下订阅的邮件周报,而且还是一个精心设计过的HTML富文本邮件。只不过它只能在pc上完美展现,在手机上最大的字号只有不到4像素,图片也变成了马赛克,会是一种怎样的虐心体验。
最近做了一个群发邮件的手机端适配需求就是要解决这个体验问题,先上效果。
优化前:
优化后:
当然,pc端和网页版也要完美适配,outlook、foxmail和网页版效果如下:
一、实现思路
参考比较常见的响应式布局,在PC端使用左图布局,移动端右图。转换时将图片的宽度由定宽改为铺满,使标题等文字换行展示。
1 邮箱渲染html的兼容性问题很多,在桌面和移动端渲染电子邮件大约有上百万种不同的组合方式,所以我们要找出一个最小子集来书写html和样式。然后用平稳退化和渐进增强的思路,对其他要适配的设备和客户端进行保底处理和浏览体验优化。
2 邮件里不能执行脚本,各种邮件客户端对media query的支持程度非常有限,所以不可能根据接收邮件的终端来构建不同的dom和cssom,必须撸一套代码适配所有终端。
3 本次迭代的目标是提升手机端阅读体验,以机端原生邮箱客户端和QQ邮箱作为基础。然后用各种hack手段来适配其他设备和客户端。比如用ghost table适配outlook,media query适配网页版等等。本次的目标是针对公司内部用户的邮件推送优化,所以覆盖的客户端和操作系统比较有限,如果要覆盖更多的设备其实原理也一样,见招拆招就好,原则就是在不影响之前已适配的设备客户端的情况下对新设备做支持。
4 移动端web的常规优化对邮件html同样适用,比如使用更小的字体、图片格式选型和压缩、高精度图片适配retina屏、用css绘制小图标代替图片等等。
二、基本原则
1 由于 OutLook从2003版本为了安全开始便使用 Word HTML 引擎进行渲染,所以我们只能使用table布局,标签也只能使用table / tr / td / span / img / a,colspan / rowspan也不能放心使用。如果要实现复杂布局,就要使用table嵌套。
2 body以外的内容全部无效,比如outlook网页版,它会把body替换成一个类名叫x_body的div,然后把body的内容全部塞进去。
3 style标签的支持程度非常碎片化,media query的支持更加有限,所以要用属性和style行内样式来保底布局。
4 邮件html里没有任何脚本。
5 不要简写样式,比如:padding: 12px 会在outlook2013失效,改为padding-left/padding-right/padding-top/padding-bottom,font简写也一样。
6 对于img标签,用属性来控制尺寸,style = “width:100px”这样的代码在outlook2013会失效,而且图片会把定宽的td和table撑开。width=”100%” 这样的css属性也是无效的。
7 Outlook 2007-2013 不支持图片的 margin 与 padding 样式,必要的时候可以尝试 hspace 和 vspace 属性(非常不建议,用父元素的margin和padding来代替就好了)。
三、实现过程中各个终端遇到的问题和解决方法
1 QQ邮箱手机客户端(版本信息:IOS11,5.6.2)
QQ邮箱收@http://qq.com的邮件,会完全过滤style标签,但是收其他域的邮件会保留style标签并且不支持media query。所以要适配QQ邮箱有两个重点。
第一就是保证行内样式渲染正常。本次最大的一个功能点就是封面图手机端铺满,pc端定宽,QQ邮箱又只能支持行内样式,所以封面图就在style里定义了宽度100%,然后针对其他设备和客户端写各种hack让它定宽。
第二是我们要用一些style样式来调整pc和网页上的布局,就要用如下办法来避免对手机QQ邮箱产生副作用。
/* 通过outlook专属标记属性来避免QQ邮箱手机版加载 */
<!--[if mso]>
<style type="text/css">
</style>
<![endif]-->
<!-- 通过media属性来避免QQ邮箱手机版加载 -->
<style type="text/css" media="screen and (min-width:900px)"></style>
2 手机原生邮件客户端(版本信息:IOS11,5.6.2)
这个最省心,支持media query,支持display:flex,在QQ手机邮箱的基础上针对原生客户端又做了一些体验优化。
3 outlook客户端(版本信息:2007-2016)
这个最麻烦,就是前面说的Word HTML 引擎。支持style,不支持media query,不支持img样式。我们这个需求最大的功能点就是在大于900宽度的屏幕上封面图按260宽渲染,在小于900宽度下铺满屏幕。outlook2013之前又只支持用attr来固定图片宽高,css定义width完全无效,还会撑破td和table),一旦写了固定值就会影响到上面说的手机邮箱客户端,怎么处理这个冲突就是关键点了。
一开始的想法比较简单,直接用style覆盖attr不就好了吗?
<img src="#" width="260" style="width:100%" >
结果outlook2016出来打脸,在pc上铺满屏了。
好,再利用outlook2016支持style的特性,用!important提高优先级覆盖回来:
<style>
img{width:260px!importnat;}
</style>
记得第一条不?手机QQ邮箱收内部邮件的时候,支持style不支持media query。这么一来手机QQ邮箱上又定宽了,被逼进绝路。
只好祭出ghost table,把用于其他客户端的那个正常的图片隐藏了,然后显示一个专门用于outlook的图。
<!--[if mso]>
<table style="display: none">
<tr>
<td>
<![endif]-->
<a href="#" class="cover">
<img src="#.jpg" border="0" width="100%">
</a>
<!--[if mso]>
</td>
</tr>
</table>
<a href="#" class="cover">
<img class="img" src="#.jpg" border="0" alt="fsight" width="260" height="150">
</a>
<![endif]-->
同理可以使用这个outlook专有的标记来隐藏所有用于其他客户端展示的dom元素,针对outlook做定制,甚至可以暴力一点写两套。
这里还遇到一个问题点就是go在渲染邮件模板的时候会自动过滤掉所有的注释,所以需要使用safe标记,并且转义写到一行内。
{{safe "<!--[if mso]> <table align=\"left\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"570\"> <tr> <td width=\"570\"> <![endif]-->" }}
code...
{{safe "<!--[if mso]></td></tr></table><![endif]-->"}}
最后就是垂直居中问题,常规的图文混排垂直居中方法就是
<div><img src="#" style="vertical-align:middle"><span style="vertical-align:middle">文字</span></div>
放到outlook里当然无效,td本身的垂直居中在各个版本中的表现也是各不相同。调试了半天,居然是给td一个定高就搞定了。
3 outlook网页版
有点小坑,它会把style里面的样式改写并且把@media里面的代码清空。
会变为:
所以使用了在style里面写media属性的方法来兼容(为了避免手机QQ邮箱会加载这段样式)。
4 QQ邮箱网页版(https://mail.qq.com)
PC版没啥好说的,完全支持各种特性,只是移动版有点小麻烦:
@media (min-width: 900px) {
.item{}
}
@media (max-width: 900px) {
.item{}
}
会被替换为
@media (min-width: 900px) {
.item{} // 仔细看这里,有个花括号被吃掉了
@media (max-width: 900px) {
.item{}
}
除了最后一个双}保留了,其他的”}}”都被替换为”}”。我估计是正则替换问题,要破也很简单,把media写到style属性,或者分多个style标签即可。
另外ipad模式下 QQ邮箱web版会出现一个宽度200的侧边栏。所以邮件正文实际使用的空间会少,写max-width的时候需要注意(你以为它有768px,实际上只有568px)。
5 mac原生客户端和foxmail客户端 (版本信息:win7.2/mac1.2)
这几个客户端也很好搞,支持media query,支持flex,可以根据屏幕大小随意定制样式。这次只是使用900px作为手机和pc的分界点。foxmail有个特性就是边栏的宽度不算在media query内,所以当左边栏拉的比较宽的时候,内容会安装手机样式渲染。
这个也好解决,在640和900之间多写几个media区间来适配就好了,体力活。
6 转发问题
通过上面的工作,系统发的邮件虽然可以适配了,但是转发的时候就还是会有问题,因为用户转发的是经过客户端处理过的邮件,要么是css不全,要么是ghost table没了。目前来看手机QQ邮箱客户端保持的最好,转发效果基本无损。其他的暂时无解,所以以防万一请在你的邮件里加上链接:“如果无法正常浏览请点击”,跳转到网页让用户查看完美的页面。
四、参考资料
1 邮件样式支持速查表:https://www.campaignmonitor.com/css/
2 outlook各版本标记:https://stackoverflow.design/email/base/mso
3 不同邮件服务商读取 HTML 邮件已知问题一览表: