Aitter's Blog

移动端高清屏适配方案

在众多移动设备中,前端开发人员如何在不同屏幕大小,不同程度的高清屏下去百分百的还原设计稿,从来都不是一件简单的事情,需要考虑众多因素,权衡利弊,做出取舍,结合需求去选择最合适的方案。

面临的问题

在不同大小和高清的屏幕下:

  • 如何保证 界面布局 一致性:不错乱,不变形
  • 如何保证 字体大小 一致性:大屏显示更大,小屏显示更小或更多
  • 如何保证 1px边框 一致性:不同的高清屏也在正常显示1px的高度大小
  • 如何保证 图片清晰度 一致性:不同大小和高清屏下都能看到清晰的图片

如果把这几个问题按重要程度排序的话,我想应该是这样的:
布局 > 字体大小 > 1px边框 > 高清图

尺寸与概念

这里不去详细介绍各种尺寸概念了,如果还有不清楚,请参考下面几篇文章,基本上都是以图片的形式介绍的非常仔细了,也完全可以做为UI设计师的参数标准!

移动端设计规范及适配尺寸
常见的移动端尺寸设计参考
iOS8 最新设计参考指南

布局

方案一 百分比布局

使用子元素在父元素下的百分比为单位,使用子元素在不同屏幕宽度下宽度表现一致
利用img标签的特性,只设宽度等图片加载完,这种方法会导致大量的重排,并且非固定高度会导致懒加载等功能难以实现
缺点:

  • 宽度可以随屏幕适应,但高度不能,宽屏下会被拉伸,具体表现为,iphone 4中看到的是正方形,而到了iphone 6s中看到的是长方形
  • 需要手动计算子元素在父元素下的百分比,计算麻烦
  • 百分比的大小往往需要精确到小数位6到8位

方案二 媒体查询调整

  • 一种是是结合百分比或flex布局,对特定的模块在特定的屏幕宽度范围内做调整
  • 另一种是结合rem, 对不同屏幕宽度范围内的设备设置不同的rem参照字体大小
    html{font-size:10px}
    @media screen and (min-width:321px) and (max-width:375px){html{font-size:11px}}
    @media screen and (min-width:376px) and (max-width:414px){html{font-size:12px}}
    @media screen and (min-width:415px) and (max-width:639px){html{font-size:15px}}
    @media screen and (min-width:640px) and (max-width:719px){html{font-size:20px}}
    @media screen and (min-width:720px) and (max-width:749px){html{font-size:22.5px}}
    @media screen and (min-width:750px) and (max-width:799px){html{font-size:23.5px}}
    @media screen and (min-width:800px){html{font-size:25px}}

缺点:
无法完全适配Android设备各种屏幕,无法保证显示的一致性,如:定义了一个模块的高度在 321 至 375下是40px,那么一个模块在这个范围的屏幕中显示就是40px,而不能随屏幕大小而变化。

方案三 flex布局

  • 类似于百分比布局,无需计算百分比,可以很好的适配所有屏幕
    手机天猫 典型的flex布局,flex做了很好的兼容处理,高度写死,可查看顶部搜索栏源码

缺点:

  • 有着和百分比布局一样的缺点,高度不便调整
  • 有几种不同的flex标准,在低端ios和安卓中有着各种各样的兼容性问题

Flex 布局DEMO

方案四 使用rem单位

和上面的几种布局方案结合使用,主要做高度调整,保证布局一致

视口不缩放使用rem

手机网易为例


分析:

  1. 根据图片可以看出网易为750的设计稿,因为750下是html字体大小是100px,这样在切图时,方便px转rem,750设计稿上是大小是50px,那么转换成rem就是.5rem(如:24px -> .24rem);
  2. px转rem简单方便
  3. 没有做1px高清屏处理
  4. 未做图片高清处理

视口缩放下使用rem

手机淘宝为例



分析:

  1. 设计稿为750的设计稿
    320 dpr=1 font-size=32px
    320 dpr=2 font-size=64px
    375 dpr=2 font-size=75px
    414 dpr=3 font-size=124.2px
    换算规则:(屏幕宽度 * dpr )/10 (除以10是为了将屏幕平分10份,为了将来替换成vm或vh单位)
  2. 屏幕根据dpr的值进行了相应的缩放
  3. 很好的还原了1px在高清屏真实度
  4. 图片使用了750下的两倍图,并没有做按dpr的值加载不同的图片
  5. px转rem需要使用工具转换

字体适配

适配规则
段落文字在大屏上希望能看到更多文字,标题文字或字数固定的文字应该应用缩放原则,随屏幕变大而变化
视口不缩放
通过媒体查询去设置不同范围内的大小
视口缩放
根据不同的dpr值去设置相应字体大小
标题文字或长度固定的文字可以使用rem单位去做适配

1px边框

使用css hack解决

使用box-shadow

-webkit-box-shadow:0 1px 1px -1px rgba(0, 0, 0, 0.5);

缺点:颜色不便控制,太淡,有虚边

使用background-image

background-image:
linear-gradient(180deg, red, red 50%, transparent 50%),
linear-gradient(270deg, red, red 50%, transparent 50%),
linear-gradient(0deg, red, red 50%, transparent 50%),
linear-gradient(90deg, red, red 50%, transparent 50%);
background-size: 100% 1px,1px 100% ,100% 1px, 1px 100%;
background-repeat: no-repeat;
background-position: top, right top, bottom, left top;

缺点:不能实现圆角1px效果,css需要做兼容处理

使用border-image

border-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAECAYAAABP2FU6AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAB5JREFUeNpiPnH8zH/G////MzAxAAHTyRNn/wMEGABpvQm9g9TJ1QAAAABJRU5ErkJggg==") 2 0 stretch;
border-width:0px 0px 1px;

缺点:边框颜色不便修改

伪类:after & transform: scale(0.5)

.box4
position relative
&:after
content ''
display block
position absolute
top -50%
left -50%
bottom -50%
right -50%
border 1px solid red
-webkit-transform scale(0.5)
transform scale(0.5)

缺点:占用了伪类,容易和原样式冲突

使用0.5px适配ios8以上的iPhone机型

@media (-webkit-min-device-pixel-ratio:2){
.box5 {border-width:.5px}
}

缺点:只适用于ios8+以上的iOS系统,安卓机不支持0.5px

iphone6 上的效果
CodePen 示例:

See the Pen 1PX 的梗 by LT (@togglelt) on CodePen.

使用视口缩放

参考手淘方案(略)

阅读参考:
移动web点5像素的秘密
再谈mobile web retina 下 1px 边框解决方案

图片高清

视口不缩放:使用@2x两倍图
视口缩放:根据不同的dpr,加载不同尺寸的图片(图片处理服务器)

手机淘宝前端的图片相关工作流程梳理

实践应用

npm install gulp-postcss postcss-px2rem –save-dev -d

处理px2rem
postcss-px2rem

.selector {
width: 150px;
height: 64px; /*px*/
font-size: 28px; /*px*/
border: 1px solid #ddd; /*no*/
}
.selector {
width: 2rem;
border: 1px solid #ddd;
}
[data-dpr="1"] .selector {
height: 32px;
font-size: 14px;
}
[data-dpr="2"] .selector {
height: 64px;
font-size: 28px;
}
[data-dpr="3"] .selector {
height: 96px;
font-size: 42px;
}

CodePen 示例

See the Pen 移动端自适用布局测试 by LT (@togglelt) on CodePen.

现有的方案
使用flexiable方案的项目
手机淘宝

hotcss和flexiable相同的方案
美丽说HIGO
奇虎360
爆米兔
新浪show

我理解的最佳实践

  • 用户体验要求很高的页面,如UV较高的页面,活动页这些应该以用户体验优先,应用flexiable方案
  • 在其它页面,固定视口,不缩放,使用rem做布局适配,js添加屏幕标识以便调整字体大小,使用@2x图片,只做ios8+的1px处理

阅读参考: