本文作者:李晓玮,腾讯 IEG 高级工程师

都2019年了,手机查看HTML邮件的体验怎么还那么差?

试想一下,你在夜深人静的时候,准备睡前查看一下订阅的邮件周报,而且还是一个精心设计过的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邮箱收@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"  >

结果outlook2016出来打脸,在pc上铺满屏了。

好,再利用outlook2016支持style的特性,用!important提高优先级覆盖回来:

<style>img{width:260px!importnat;}
</style>

记得第一条不?手机QQ邮箱收内部邮件的时候,支持style不支持media query。这么一来手机QQ邮箱上又定宽了,被逼进绝路。

只好祭出ghost table,把用于其他客户端的那个正常的图片隐藏了,然后显示一个专门用于outlook的图。

<!--[if mso]>
<table ><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="#" ><span  >文字</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 邮件已知问题一览表:

http://app1.studiocloud.com/support/index.php?/article/AA-00861/0/Issues-with-HTML-Emails-in-Different-Email-Clients.html

文章中的链接如无法打开,可以点击下方链接跳转到知乎查看,喜欢记得点赞收藏!

欢迎关注腾讯 WeTest:

HTML 文件在PC移动端完美自适应布局的技巧相关推荐

  1. android中自适应布局教程,Android自适应布局设计技巧

    由于目前在做的一款app需要适配手机和平板,所以我在研究怎么构建可适应所有屏幕尺寸的布局方法. 在web的自适应布局上我有很多经验,比如使用网格流,CSS3中的media queries属性等等,这些 ...

  2. wordpress自适应表格_wordpress响应式移动端完美自适应宽屏主题

    WordPress移动宽屏主题HTML5+CSS3响应式布局,这款主题在我很久以前就在找的,之前我是比较倾向于特别宽的网站总感觉很窄的网页让人喘不过气,看着很难受,不过可惜那时没有找到,如果当年找到了 ...

  3. 移动端屏幕自适应布局

    1.技术点 移动端自适应采用百分比布局比较适合.需要说明一点的是:height的百分比是以父元素的宽度计算的,由于移动端父元素宽度有时没有给定值(如父元素宽度为100%),此时子元素的height就为 ...

  4. 移动端h5框架自适应_Html5移动端页面自适应百分比布局

    按百分比布局,精度肯定不会有rem精确 Document * { padding: 0; margin: 0; } .one { width: 20%; height: 100px; float: l ...

  5. vue适配PC端屏幕自适应

    vue适配PC端屏幕自适应 1.下载postcss-px2rem和px2rem-loader npm i postcss-px2rem px2rem-loader 2.src目录下新建utils文件夹 ...

  6. vue PC+移动端 自适应布局

    之前自己接了个项目 PC+移动端 自动适配显示,因为手机端需要自适应,pc也是需要自适应 项目里 PC用的1920px,移动端用的375px,使用媒体查询适配显示 一.环境 使用lib-flexibl ...

  7. vue项目实现大屏PC端字体自适应

    vue项目实现大屏PC端字体自适应 我们字体自适应选择使用rem作为单位,通过监听窗口大小的变化,更新1rem的对应的px数来实现字体自适应. 注意该方法,我们需要在APP.vue文件中实现, 首先A ...

  8. PHP匿名在线聊天室系统源码 自适应PC+WAP端

    介绍: PHP匿名在线聊天室系统源码 自适应PC+WAP端 可发语音.图片 修改数据库config\settings.php可拿去搭建专门跟客户聊天的网站 网盘下载地址: http://kekewl. ...

  9. Xiuno修罗轻论坛仿知乎蓝简约响应式主题模板1.7+自适应PC+WAP端

    Xiuno修罗轻论坛仿知乎蓝简约响应式主题模板1.7+自适应PC+WAP端 ☑️ 编号:ym445 ☑️ 品牌:无 ☑️ 语言:php ☑️ 大小:66KB ☑️ 类型:修罗轻论坛 ☑️ 支持:pc+ ...

最新文章

  1. 3D U-Net:从稀疏注释中学习密集的体积分割
  2. 快速搭建一个restful风格的springboot项目
  3. 50句看后可以变换心情豁然开朗的话
  4. 【转】RabbitMQ六种队列模式-3.发布订阅模式
  5. html加上百度统计,vue单页面应用加入百度统计
  6. c++-add two numbers 两个链表相加
  7. ae saber插件_【AE插件】 用于做动画制作/设计的五个免费插件 非常好用
  8. Spring:@Configuration和@Component的使用与区别
  9. 搜狗王小川:搜狗的语音识别比阿里和科大讯飞的好
  10. 不用编程实现PLC之间通讯-西门子与三菱以太网实时通讯
  11. 【DIY】热水器升级加装远程wifi控制功能,esp8266远程红外控制热水器启动
  12. MacOS 开发 —后台启动程序
  13. Vue + Element-UI —— 项目实战(一)
  14. 房东要涨800房租,我用Python抓取帝都几万套房源信息,主动涨了1000。
  15. goproxy代理软件 v10.3 轻量级高性能代理软件+链式代理+正向代理+反向代理
  16. 等保2.0落地解读与实践分析
  17. Mysql语句商城系统表案例
  18. 面向对象编程基本概念
  19. 雷电3接口 显卡 linux,炫龙 耀7000有雷电3接口么?
  20. 【公益创投】“爱无限·心关爱”2021心理情景剧剧本征集活动结果出炉啦!

热门文章

  1. mysql中varchar与integer的互转
  2. CodeForces - 894B Ralph And His Magic Field(组合数学+思维)
  3. CH - 0501 货仓选址(中位数)
  4. (转)KMP的next数组模板
  5. HUST - 1016 幼儿园小朋友们的难题(水题)
  6. HDU - 5978 To begin or not to begin(简单博弈)
  7. 开源oracle client,oracle client安装与配置
  8. python k线图 动态刷新不了_ImageButton点击之后不动态刷新页面的解决方案
  9. 大数开方(Java版)
  10. Catalan数推导及应用