移动端适配

作为一个前端开发人员,我们的任务是将UI设计师的图稿运用计算机语言呈现在用户面前。而现在的设备大小尺寸不一,近年来智能手机的普及更是让网页的用户大部分来源与手机,所以让不同大小的移动端屏幕都能较好的还原设计稿就成了一个前端开发者需要解决的当务之急。我查阅了大量资料和进行了一些实践,下面是我对移动端适配的一些认识。

首先我们来谈谈我们在电脑端用的字体单位px和em

在国内的网站中大多都是使用px作为字体单位,只有百度做了个可调的表率。而在大洋彼岸,几乎所有的主流站点都使用em作为字体单位,也就是可调的。他们为什么要用em作为单位呢,主要有一下几个原因

  • IE无法调整那些使用px作为单位的字体大小;
  • 国外的大部分网站能够调整的原因在于其使用了em作为字体单位;
  • Firefox能够调整px和em,但是96%以上的中国网民使用IE浏览器(或内核)。

px和em概念

px像素(Pixel): 相对长度单位。像素px是相对于显示器屏幕分辨率而言的。
em:是相对长度单位。相对于当前对象内文本的字体尺寸。如当前对行内文本的字体尺寸未被人为设置,则相对于浏览器的默认字体尺寸。

任意浏览器的默认字体高都是16px。所有未经调整的浏览器都符合: 1em=16px。那么12px=0.75em,10px=0.625em。为了简化font-size的换算,需要在css中的body选择器中声明 Font-size=62.5%,这就使em值变为 16px*62.5%=10px, 这样12px=1.2em, 10px=1em, 也就是说只需要将你的原来的px数值除以10,然后换上em作为单位就行了。

em有如下特点:
  1. em的值并不是固定的;
  2. em会继承父级元素的字体大小。
所以我们在写CSS的时候,需要注意两点:
  1. body选择器中声明Font-size=62.5%;
  2. 将你的原来的px数值除以10,然后换上em作为单位;
  3. 重新计算那些被放大的字体的em数值。避免字体大小的重复声明。

下面我们来谈谈移动端的适配方案

首先讲讲一个基本概念

视窗 viewport

移动前端中常说的 viewport (视口)就是浏览器显示页面内容的屏幕区域。

移动端的viewport太窄,为了能更好为CSS布局服务,所以提供了两个viewport:虚拟的visual viewport和布局的layout viewport。

layout viewport(布局视口)

一般移动设备的浏览器都默认设置了一个viewport 元标签,定义一个虚拟的layout viewport(布局视口),用于解决早期的页面在手机上显示的问题。iOS, Android基本都将这个视口分辨率设置为 980px,所以pc上的网页基本能在手机上呈现,只不过元素看上去很小,一般默认可以通过手动缩放网页。

这里是一个小demo,分别是加了<meta name="viewport" content="width=device-width,initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">和没加页面的效果


加了

没加
visual viewport(视觉视口)和物理像素

visual viewport(视觉视口)备物理屏幕的可视区域,屏幕显示器的物理像素,同样尺寸的屏幕,像素密度大的设备,硬件像素会更多。例如iPhone的物理像素:

  • iPhone5 :640 * 1136
  • iPhone6:750 * 1334
  • iPhone6 Plus:1242 * 2208
ideal viewport(理想视口)和 dip (设备逻辑像素)

ideal viewport(理想视口)通常是我们说的屏幕分辨率。

dip (设备逻辑像素)跟设备的硬件像素无关的。一个 dip 在任意像素密度的设备屏幕上都占据相同的空间。

比如MacBook Pro的 Retina (视网膜)屏显示器硬件像素是:2880 * 1800。当你设置屏幕分辨率为 1920 * 1200 的时候,ideal viewport(理想视口)的宽度值是1920像素, 那么 dip 的宽度值就是1920。设备像素比是1.5(2880/1920)。设备的逻辑像素宽度和物理像素宽度(像素分辨率)的关系满足如下公式:

逻辑像素宽度*倍率 = 物理像素宽度

而移动端手机屏幕通常不可以设置分辨率,一般都是设备厂家默认设置的固定值,换句话说 dip 的值就是 ideal viewport(理想视口)(也就是分辨率)的值,比如,iPhone的屏幕分辨率:

iPhone5 :分辨率 320 * 568,物理像素 640 * 1136,@2x
iPhone6:分辨率 375 * 667,物理像素 750 * 1334,@2x
iPhone6 Plus :分辨率 414 * 736,物理像素1242 * 2208,@3x

所以我们需要使用viewport元标签控制布局

通常用到的适配代码

<meta name="viewport" content="width=device-width,initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">

这里是每个属性的详细介绍


width

为了是适应布局,我们一般将width设为device-width。

width=device-width 也就是将layout viewport(布局视口)的宽度设置 ideal viewport(理想视口)的宽度。网页缩放比例为100%时,一个CSS像素就对应一个 dip(设备逻辑像素),而layout viewport(布局视口)的宽度,ideal viewport(理想视口)的宽度(通常说的分辨率),dip 的宽度值是相等的。

initial-scale

initial-scale用于指定页面的初始缩放比例:

  • initial-scale=1 表示将layout viewport(布局视口)的宽度设置为 ideal viewport(理想视口)的宽度,
  • initial-scale=1.5 表示将layout viewport(布局视口)的宽度设置为 ideal viewport(理想视口)的宽度的1.5倍。

因为分辨率和物理像素的关系,所以我们就需要通过js来确定页面的初始缩放比例,下面是控制初始缩放比例的代码。后面会进行解释

var i = e.navigator.appVersion.match(/iphone/gi) ? e.devicePixelRatio :1, 
    a = 1 / i, 

然后我们谈谈rem

rem其实和em非常相似,在w3c中是这样描述rem的

font size of the root element.

它的用法和em差不多,区别是em是针对父元素的font-size做计算,而rem是相对与根元素<html>做计算。我们在移动端使用rem作为所有大小的单位来解决适配的问题。

我们设置根元素font-size的大小,应该是不同屏幕设置不一样的。比如一个740大的屏幕,我们会把它的font-size设为76px;而一个370大的屏幕,我们会把它的font-size设为34px,这要根据屏幕大小而言。

所以,我们需要编写一个js文件来适应不同的屏幕

这是某个网站的移动适配js,这里通过这个文件做一些解释

!function(e) {
    function t() {
        e.rem = d.getBoundingClientRect().width / 16, d.style.fontSize = e.rem + "px";
    }
    var n, 
        i = e.navigator.appVersion.match(/iphone/gi) ? e.devicePixelRatio :1, 
        a = 1 / i, 
        d = document.documentElement, 
        o = document.createElement("meta");
    if (e.dpr = i, 
        e.addEventListener("resize", function() {
        clearTimeout(n), n = setTimeout(t, 300);
    }, !1), 
        e.addEventListener("pageshow", function(e) {
        e.persisted && (clearTimeout(n), n = setTimeout(t, 300));
    }, !1), 
        d.setAttribute("data-dpr", i), o.setAttribute("name", "viewport"), 
        o.setAttribute("content", "initial-scale=" + a + ", maximum-scale=" + a + ", minimum-scale=" + a + ", user-scalable=no"), d.firstElementChild) 
        d.firstElementChild.appendChild(o); 
    else {
        var m = document.createElement("div");
        m.appendChild(o), document.write(m.innerHTML);
    }
    t();
}(window), document.addEventListener("DOMContentLoaded", function() {
    var e = document.createElement("input");
    e.type = "hidden", 
    e.value = '{"platform": "qq_qzone_weixin_weibo_copy","title":"","desc": "","image":"","comment": "", "url":"","callback":"shareCallback()"}', 
    e.id = "app_share_conf", document.getElementsByTagName("body")[0].appendChild(e);
}, !1);

把视觉稿中的px转换成rem

我们在开发过程中拿到的设计稿都是以px作为单位的,那我们在进行移动端编程的时候该怎样对应rem大小呢?

e.rem = d.getBoundingClientRect().width / 16

这段代码的意思是把屏幕分成16份,根元素的font-size就等于屏幕大小/分成份数。当然我们不一定要把屏幕分成16份,比如淘宝的Flexible.js将屏幕分成10份。

缩放比例

前面已经提到,针对不同的设备,屏幕分辨率和物理像素的倍速不同所以我们要通过获取设备来设置缩放比例。

var  i = e.navigator.appVersion.match(/iphone/gi) ? e.devicePixelRatio :1, 
     a = 1 / i,

关于移动适配的meta标签,我们是不用事先编写的,通过这个js文件,将自动创建meta标签。

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