懒人必备的移动端定宽网页适配方案

 

现在移动设备的分辨率纷繁复杂。之前仅仅是安卓机拥有各类各样的适配问题,现在 iPhone 也拥有了三种主流的分辨率,而将来的 iPhone 7 可能又会玩出什么新花样。如何以不变应万变,用简简单单的几行代码就能支持种类繁多的屏幕分辨率呢?今天就给你们介绍一种懒人必备的移动端定宽网页适配方法。javascript

首先看看下面这行代码:html

<meta name="viewport" content="width=device-width, user-scalabel=no">

有过移动端开发经验的同窗是否是对上面这句代码很是熟悉?它可能最多见的响应式设计的 viewport 设置之一,而我今天介绍的这种方法也是利用了 meta 标签设置 viewport 来支持大部分的移动端屏幕分辨率。java

目标

  • 仅仅经过配置 <meta name="viewport"> 使得移动端网站只须要按照固定的宽度设计并实现,就能在任何主流的移动设备上都能看到符合设计稿的页面,包括 Android 4+、iPhone 4+。

测试设备

  • 三星 Note II (Android 4.1.2) - 真机
  • 三星 Note III (Android 4.4.4 - API 19) - Genymotion 虚拟机
  • iPhone 6 (iOS 9.1) - 真机

iPhone

iPhone 的适配比较简单,只须要设置 width 便可。好比:android

<!-- for iPhone --> <meta name="viewport" content="width=320, user-scalable=no" />

这样你的页面在全部的 iPhone 上,不管是 宽 375 像素的 iPhone 6 仍是宽 414 像素的 iPhone 6 plus,都能显示出定宽 320 像素的页面。web

Android

Android 上的适配被戏称为移动端的 IE,确实存在着不少兼容性问题。Android 以 4.4 版本为一个分水岭,首先说一说相对好处理的 Android 4.4+app

Android 4.4+

为了兼容性考虑,Android 4.4 以上抛弃了 target-densitydpi 属性,它只会在 Android 设备上生效。若是对这个被废弃的属性感兴趣,能够看看下面这两个连接:iphone

咱们能够像在 iPhone 上那样设置 width=320 以达到咱们想要的 320px 定宽的页面设计。测试

<!-- for Android 4.4+ --> <meta name="viewport" content="width=320, user-scalable=no" />

Android 4.0 ~ 4.3

做为 Android 相对较老的版本,它对 meta 中的 width 属性支持得比较糟糕。以三星 Note II 为例,它的 device-width 是 360px。若是设置 viewport 中的 width (如下简称 vWidth ) 为小于等于 360 的值,则不会有任何做用;而设置 vWidth 为大于 360 的值,也不会使画面产生缩放,而是出现了横向滚动条。网站

想要对 Android 4.0 ~ 4.3 进行支持,仍是不得不借助于页面缩放,以及那个被废除的属性:target-densitydpispa

target-densitydpi

target-densitydpi 一共有四种取值:low-dpi (0.75), medium-dpi (1.0), high-dpi (1.5), device-dpi。在 Android 4.0+ 的设备中,device-dpi 通常都是 2.0。我使用手头上的三星 Note II 设备 (Android 4.1.2) 进行了一系列实验,获得了下面这张表格:

target-densitydpi viewport: width body width 屏幕可视范围宽度
low-dpi (0.75) vWidth <= 320 270 270
  vWidth > 320 vWidth* 270
medium-dpi (1.0) vWidth <= 360 360 360
  vWidth > 360 vWidth* 360
high-dpi (1.5) vWidth <= 320 540 540
  320 < vWidth <= 540 vWidth* vWidth*
  vWidth > 540 vWidth* 540
device-dpi (2.0)** vWidth <= 320 720 720
  320 < vWidth <= 720 vWidth* vWidth*
  vWidth > 720 vWidth* 720
  • vWidth*:指的是与 viewport 中设置的 width 的值相同。
  • device-dpi (2.0)**:在 Android 4.0+ 的设备中,device-dpi 通常都是 2.0。

首先能够看到 320px 是个特别诡异的临界值,低于这个临界值后就会发生超出咱们预期的事情。综合考虑下来,仍是采用 target-densitydpi = device-dpi 这一取值。若是你想要以 320px 做为页面的宽度的话,我建议你针对安卓 4.4 如下的版本设置 width=321

若是 body 的宽度超过屏幕可视范围的宽度,就会出现水平的滚动条。这并非咱们指望的结果,因此咱们还要用到缩放属性 initial-scale。计算公式以下:

Scale = deviceWidth / vWidth

这样的计算式不得不使用 JS 来实现,最终咱们就能获得适配 Android 4.0 ~ 4.3 定宽的代码:

var match, scale, TARGET_WIDTH = 320; if (match = navigator.userAgent.match(/Android (\d+\.\d+)/)) { if (parseFloat(match[1]) < 4.4) { if (TARGET_WIDTH == 320) TARGET_WIDTH++; var scale = window.screen.width / TARGET_WIDTH; document.querySelector('meta[name="viewport"]').setAttribute('content', 'width=' + TARGET_WIDTH + ', initial-scale = ' + scale + ', target-densitydpi=device-dpi'); } }

其中,TARGET_WIDTH 就是你所指望的宽度,注意这段代码仅在 320-720px 之间有效哦。

缩放中的坑

若是是 iPhone 或者 Android 4.4+ 的机器,在使用 scale 相关的属性时要很是谨慎,包括 initial-scalemaximum-scale 和 minimum-scale。 要么保证 Scale = deviceWidth / vWidth,要么就尽可能不用。来看一个例子:

Android 4.4+ 和 iPhone 在缩放时的行为不一致

在缩放比不能保证的状况下,即便设置一样的 width 和 initial-scale 后,二者的表现也是不一致。具体两种机型采用的策略如何我尚未探索出来,有兴趣的同窗能够研究看看。最省事的办法就是在 iPhone 和 Android 4.4+ 上不设置 scale 相关的属性。

总结

结合上面全部的分析,你能够经过下面这段 JS 代码来对全部 iPhone 和 Android 4+ 的手机屏幕进行适配:

var match, scale, TARGET_WIDTH = 320; if (match = navigator.userAgent.match(/Android (\d+\.\d+)/)) { if (parseFloat(match[1]) < 4.4) { if (TARGET_WIDTH == 320) TARGET_WIDTH++; var scale = window.screen.width / TARGET_WIDTH; document.querySelector('meta[name="viewport"]').setAttribute('content', 'width=' + TARGET_WIDTH + ', initial-scale = ' + scale + ', target-densitydpi=device-dpi'); } } else { document.querySelector('meta[name="viewport"]').setAttribute('content', 'width=' + TARGET_WIDTH); }

若是你不但愿你的页面被用户手动缩放,你还能够加上 user-scalable=no。不过须要注意的是,这个属性在部分安卓机型上是无效的哦。

其余参考资料

  1. Supporting Different Screens in Web Apps - Android Developers
  2. Viewport target-densitydpi support is being deprecated

附录 - 测试页面

有兴趣的同窗能够拿这个测试页面来测测本身的手机,别忘了改 viewport 哦。

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=250, initial-scale=1.5, user-scalable=no"> <title>Document</title> <style> body { margin: 0; } div { background: #000; color: #fff; font-size: 30px; text-align: center; } .block { height: 50px; border-bottom: 4px solid #ccc; } #first { width: 100px; } #second { width: 200px; } #third { width: 300px; } #fourth { width: 320px; } #log { font-size: 16px; } </style> </head> <body> <div id="first" class="block">100px</div> <div id="second" class="block">200px</div> <div id="third" class="block">300px</div> <div id="fourth" class="block">320px</div> <div id="log"></div> <script> function log(content) { var logContainer = document.getElementById('log'); var p = document.createElement('p'); p.textContent = content; logContainer.appendChild(p); } log('body width:' + document.body.clientWidth) log(document.querySelector('[name="viewport"]').content) </script> </body> </html>
相关文章
相关标签/搜索