H5 高清适配

问题的由来

手机屏幕的分辨率差异很大。

iphone4:320×480

iphone6:375×667

H5 网页必须自动适应这些屏幕,包含以下三部分的工作。

布局的缩放

字体的大小

图片的适配

retina 屏幕

有些设备是高清屏(retina),物理像素在水平方向和垂直方向各压缩 50% 显示。

这时,CSS 里面的 1 个像素会对应 4 个物理像素。

width: 20px;height: 20px;

retina 设备中,一张 40 x 40 像素的图片,会占据 20 x 20 的屏幕空间。如果图像比 40 x 40 像素小,就会显得比较模糊。

所以,图片往往需要准备非 retina 和 retina 两个版本。比如,200×300 的图片,还要准备 400×600 的版本。

SASS 的写法。

@mixinimg-dpr(){background-image: url(image.jpg);//默认[data-dpr="2"]&{background-image: url(image@2x.jpg);//两倍高清}      [data-dpr="3"] & {background-image: url(image@3x.jpg);//三倍高清}}.content{@includeimg-dpr(); }

dpr

高清屏的物理像素与实际像素的关系,可以用下面的公式表示。

设备像素比 = 物理像素 / 设备独立像素

“设备像素比”(device-pixel-ratio)简称为dpr。

iPhone4~iPhone6:dpr = 2

iPhone 6+:dpr = 3

对于 dpr 等于 2 的设备,视觉稿的画布水平/垂直大小会是基准的2倍,也就是说像素点个数是原来的4倍。比如,对于 iphone6 而言来说,屏幕大小是 375×667,视觉稿就是 750×1334。

脚本中可以使用window.devicePixelRatio得到dpr。

console.log(window.devicePixelRatio)// 2

高清屏的 CSS 设置

使用 CSS 的 Media Query,可以针对不同的屏幕设置不同的 CSS 规则。

@media(-webkit-min-device-pixel-ratio:2),        (min-resolution:2dppx),        (min-resolution:192dpi)  {/* 高清屏的 CSS 规则 */}

区分 retina 屏幕和屏幕宽度的 CSS 设置,完整写法如下。

@mediaonly screen and (min-width:320px) {/* 非 retina 的小屏幕 */}@mediaonly screen and (-webkit-min-device-pixel-ratio:2)      and (min-width:320px),only screen and (  min--moz-device-pixel-ratio:2)      and (min-width:320px),only screen and (    -o-min-device-pixel-ratio:2/1)    and (min-width:320px),only screen and (        min-device-pixel-ratio:2)      and (min-width:320px),only screen and (                min-resolution:192dpi) and (min-width:320px),only screen and (                min-resolution:2dppx)  and (min-width:320px) {/* 小屏幕的 retina 屏 */}@mediaonly screen and (min-width:700px) {/* 中等的非 retina 屏 */}@mediaonly screen and (-webkit-min-device-pixel-ratio:2)      and (min-width:700px),only screen and (  min--moz-device-pixel-ratio:2)      and (min-width:700px),only screen and (    -o-min-device-pixel-ratio:2/1)    and (min-width:700px),only screen and (        min-device-pixel-ratio:2)      and (min-width:700px),only screen and (                min-resolution:192dpi) and (min-width:700px),only screen and (                min-resolution:2dppx)  and (min-width:700px) {/* 中等屏幕的 retina 屏 */}@mediaonly screen and (min-width:1300px) {/* 大屏幕的非 retina 屏 */}@mediaonly screen and (-webkit-min-device-pixel-ratio:2)      and (min-width:1300px),only screen and (  min--moz-device-pixel-ratio:2)      and (min-width:1300px),only screen and (    -o-min-device-pixel-ratio:2/1)    and (min-width:1300px),only screen and (        min-device-pixel-ratio:2)      and (min-width:1300px),only screen and (                min-resolution:192dpi) and (min-width:1300px),only screen and (                min-resolution:2dppx)  and (min-width:1300px) {/* 大屏幕的 retina 设备 */}

页面 Scale

页面如何缩放,才能适应屏幕的大小?

宽度自适应

rem 方法

宽度自适应方法

网页元素的宽度设成百分比或vw单位,或者采用 flex 布局。

视口自动缩放,使得宽度自动适应网页大小。

width=device-width,

initial-scale=1.0,

minimum-scale=1.0,

maximum-scale=1.0,

user-scalable=no

">

缺点:宽度可以自适应,但是没法规定高度,容器会有一定程度的变形。

rem 方法

另一种方法是使用rem单位,所有网页元素的宽度和高度都设成rem单位,因此不会有变形问题。

视口不用缩放,只需要指定根元素的font-size大小。然后,根据不同网页的宽度,动态改变根元素的font-size,来调节容器的大小。

比如,设计稿的默认宽度是 750 px,为了便于计算,对应的font-size指定为1rem = 100px。如果设备的宽度是 375 px,就用脚本将font-size改为1rem = 50px。那么,某个网页元素的宽度是0.5rem,在 750px 设备下是50px,在 375px 设备下是25px。

下面就是脚本改写font-size的例子。

(function(doc, win){vardocEl = doc.documentElement;varresizeEvt ='orientationchange'inwindow?'orientationchange':'resize';varrecalc =function(){varclientWidth = docEl.clientWidth;if(!clientWidth)return;    docEl.style.fontSize =100* (clientWidth /750) +'px';  };  win.addEventListener(resizeEvt, recalc,false);  doc.addEventListener('DOMContentLoaded', recalc,false);})(document,window);

不使用 JS,单纯使用 CSS 也可以设置font-size的大小。

@media screen and (min-width:320px) {html {font-size:100px;}}@media screen and (min-width:360px) {html {font-size:112.5px;}}@media screen and (min-width:400px) {html {font-size:125px;}}@media screen and (min-width:440px) {html {font-size:137.5px;}}@media screen and (min-width:480px) {html {font-size:150px;}}

为了解决1px的 border 的问题(见后文),可以指定页面宽度,然后将页面放大dpr倍,再缩小为1/dpr,脚本代码如下。

vardpr, rem, scale;vardocEl =document.documentElement;varfontEl =document.createElement('style');varmetaEl =document.querySelector('meta[name="viewport"]');dpr =window.devicePixelRatio ||1;rem = docEl.clientWidth * dpr /10;scale =1/ dpr;// 设置viewport,进行缩放,达到高清效果metaEl.setAttribute('content','width='+ dpr * docEl.clientWidth    +',initial-scale='+ scale    +',maximum-scale='+ scale    +', minimum-scale='+ scale    +',user-scalable=no');

比如,对于iphone5(dpr=2),meta标签如下。

然后,结合屏幕宽度和 dpr 后算出 font-size (基准为 32px)。

320px 屏幕, dpr=1 ,font-size=32px

320px 屏幕, dpr=2 ,font-size=64px

375px 屏幕, dpr=2 ,font-size=75px

414px 屏幕, dpr=3, font-size=124.2px

计算规则:(屏幕宽度 * dpr ) / 10

“屏幕宽度”可以用document.documentElement.clientWidth得到。乘以dpr,是因为页面有可能为了实现1pxborder页面会缩放(scale)1/dpr倍(如果没有,则dpr=1)。

字体大小

使用了rem单位之后,页面元素会随着屏幕的增大而等比例放大,但是某些内容我们不愿意被放大,例如正文段落,而是为显示更多的文字,这时文字不使用rem作为单位,而是用px。

font-size:16px;[data-dpr="2"] input {  font-size:32px;}

上面代码中,默认字体大小是 16px,retina 设备就是 32px。

举例: iphone6 的屏幕适配

一个针对 iphone6 的高清视觉稿 750×1334

在psd文件中量出:宽高 750×300px 的div,那么如何转换成rem单位呢?

公式如下:

rem = px / 基准值;

对于一个iphone6的视觉稿,它的基准值就是75(之前有提到)。

转成 HTML 就是如下。

width: 10rem; // -> 750px

height: 4rem; // -> 300px

最后因为dpr为2,页面scale了0.5,所以在手机屏幕上显示的真实宽高应该是375×150px,就刚刚好。

1px 边框问题

高清屏下,border: 1px会显得太宽,但是安卓设备的border又不能设成 0.5 px,可以参考下面的链接。

mobile web retina下1px解决方案升级版

移动端高清屏适配方案

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,362评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,330评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,247评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,560评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,580评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,569评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,929评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,587评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,840评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,596评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,678评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,366评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,945评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,929评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,165评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,271评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,403评论 2 342

推荐阅读更多精彩内容

  • AMD 和 CMD 的区别有哪些?AMD 是 RequireJS 在推广过程中对模块定义的规范化产出。CMD 是 ...
    竿牍阅读 686评论 0 1
  • -----BEGIN PGP MESSAGE-----Version: GnuPG v2 hQEMAzxIntHP...
    HapLeo阅读 254评论 0 0
  • 1、散步,不是真的散步,而是一张一驰,该快的时候,迅速出手,你可以看林丹打球,仿佛就是在走路,但是瞬间启动是一流的...
    瓜瓜日记阅读 252评论 0 0
  • 总是无法忍耐太多 总是不能包容所有 总是不解你的风情 总是难懂你的感受 就让我享受孤独 就让我变得安静 就让我回到...
    悠然_3c09阅读 103评论 4 2