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

标签: 移动端适配 移动端页面 javascript viewport android | 发表时间:2015-12-08 13:49 | 作者:JerryZou
出处:http://segmentfault.com/blogs

本文最初发布于我的个人博客: 咀嚼之味

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

首先看看下面这行代码:

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

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

目标

  • 仅仅通过配置 <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 即可。比如:

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

这样你的页面在所有的 iPhone 上,无论是 宽 375 像素的 iPhone 6 还是宽 414 像素的 iPhone 6 plus,都能显示出定宽 320 像素的页面。

Android

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

Android 4.4+

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

我们可以像在 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-densitydpi

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-scale, maximum-scaleminimum-scale
要么保证 Scale = deviceWidth / vWidth,要么就尽量不用。来看一个例子:

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

在缩放比不能保证的情况下,即时设置同样的 widthinitial-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>

相关 [移动 网页 配方] 推荐:

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

- - SegmentFault 最新的文章
本文最初发布于我的个人博客: 咀嚼之味. 如今移动设备的分辨率纷繁复杂. 以前仅仅是安卓机拥有各种各样的适配问题,如今 iPhone 也拥有了三种主流的分辨率,而未来的 iPhone 7 可能又会玩出什么新花样. 如何以不变应万变,用简简单单的几行代码就能支持种类繁多的屏幕分辨率呢. 今天就给大家介绍一种懒人必备的移动端定宽网页适配方法.

从基本文本网页至移动网页设计,网页设计全历史

- Kione - 互联网的那点事
从1990年代初的基本文本编辑的网页开始,1990年代中期的在线网页建设,到上世纪90年代末崛起的flash,再到后来的CSS和Javasvript的崛起,直到现在web 2.0时代鼎盛时期,网页设计经历了多次变革. 这里介绍和突出了,不同时期里面网页设计的各方面的关键特点. 编辑/翻译: Viking Wong@DamnDigital 图片编辑: Qi Wong@DamnDigital 原文: Kissmetrics.

5大移动网页设计之最佳实践

- everfly - 互联网的那点事
本文来自SocialBeta内容贡献者wisp,原文译自Mobile Web Design: Best Practices,更多移动产品设计方面的资料,请查看SocialBeta移动互联网栏目. 移动设备的兴起正在给互联网带来一场新的革命,虽然说移动网页设计原则不会有多大变化,但是却有着明显的区别.

开发移动版网页的技巧:一个案例

- 没剑 - 爱范儿 · Beats of Bits
在智能手机日益普遍的今天,网页设计必须考虑到小屏幕智能手机的要求. 专门开发手机应用自然是一个不错的方案,但是毕竟耗费精力,况且还需要针对不同设备进行开发和维护. 开发移动版网页是另一个不错的选择. 这件事情看起来简单,却也有许多细节和门道. Useit 网站最近的一篇文章对手机版网页设计的探讨值得参考.

给力!LibreOffice也将开发网页版以及移动版

- 欧剃 - 文章栏目
LibreOffice官方宣布将尝试开发网页版、Android版、ios版的办公程序,预计会在明年底或后年发布这些产品. 网页版的LibreOffice将使用GTK+框架,用HTML5来写界面.

Parse将推出Javascript SDK支持移动网页应用

- - CocoaChina移动观察
文/Kim-Mai Culter. 由美国知名创业孵化器Y Combinator支持的创业Parse曾为面向移动应用(如Band of the Day 和Hipmunk)提供后端支持,宣布将为移动网络应用提供支持. 这家位于旧金山的创业公司提供了面向JavaScript的SDK,实现更为方便的创建HTML5应用.

不管移动端还是PC 网页都将超越App

- - 派代网 - 资讯
      据国外媒体报道,风投公司Andreessen Horowitz的联合创始人马克·安德森(Marc Andreessen)表示,他依然看好桌面端的发展前景.       打个比方,如果我们这代人从小就生活在只有平板电脑和智能手机的世界里. 突然有一天,有人开始使用一种有着27英寸显示屏的笔记本电脑.

移动设备网页中快速响应单击动作

- - 博客园_首页
下文中的内容主要是在iOS平台测试,参考资料也主要是Apple的关于移动平台Web页面开发的书籍. 现在主流的移动设备,例如智能手机、iPad、Android平板电脑等,都没有鼠标输入设备,只是通过手指触摸屏幕来实现用户交互. 而传统的网页大都针对鼠标输入设备进行页面元素的事件绑定,例如:mouseover, mousemove, mousedown, mouseup, click.

响应性网页VS移动App,创业者该选哪个?

- - 创业邦
  到底是设计一个各种设备都可以使用的响应性网页还是创建移动App. 这是一个让许多企业家和创业者都很苦恼的问题. 深入研究时就会发现不管是哪种选择,都同时显现出了优缺点并且均需纳入衡量范围中. 这也是为什么很难做出选择的原因.   自去年起,零售方面App的使用占据了消费者27%的时间,这体现出移动设备App对于线上用户的影响十分强大.

【译】Hybrid移动应用:用网页技术提供Native体验

- - 携程设计委员会
原文: http://www.smashingmagazine.com/2014/10/21/providing-a-native-experience-with-web-technologies/. 翻译: 叮当当咚当当小胖妞呀 杀手爱elva Ivan_z3 肖弦. 根据最近的一篇 报告显示,HTML是移动应用开发人员使用最多的语言,开发人员对于选择哪种网页技术考虑的最主要因素,是代码的跨平台便携性和开发的低成本性.