移动和pc网页布局适配多设备

一.视口(viewport)

viewport视口

viewport是严格的等于浏览器的窗口。viewport与跟viewport有关的meta标签的关系,详细建议读一读这篇文章:移动前端开发之viewport的深入理解,viewport与布局的关系,可以看下这篇文章:在移动浏览器中使用viewport元标签控制布局

visual viewport 可见视口  屏幕宽度

layout viewport 布局视口 DOM宽度

ideal viewport 理想适口:使布局视口就是可见视口

设备宽度(visual viewport)与DOM宽度(layout viewport), scale的关系为:

(visual viewport)= (layout viewport)* scale

获取屏幕宽度(visual viewport)的尺寸:window. innerWidth/Height。

获取DOM宽度(layout viewport)的尺寸:document. documentElement. clientWidth/Height。

设置理想视口:把默认的layout viewport的宽度设为移动设备的屏幕宽度,得到理想视口(ideal viewport):

我们进行网页布局的时候设置html元素宽度为100%,这个100%是依据什么设置的呢?浏览器窗口用CSS像素衡量的宽度(window.innerWidth)还是别的呢?我们可以发现在PC端的浏览器上设置100%,html元素的px宽度就等于浏览器宽度;而在移动端不管是在什么设备上,html设置100%,基本上宽度都等于980px,这里的980px就是移动端所谓的布局视口了。

在移动端,默认的情况下,布局视口的宽度是要远远大于浏览器的宽度的。这两个视口不同于PC端,是相互独立存在的。浏览器厂商为了让用户在小屏幕下网页也能够显示地很好,所以把布局视口宽度设置地很大,一般在768px ~ 1024px之间,最常见的宽度是980px。这个宽度可以通过document.documentElement.clientWidth得到。

移动端布局需要达到的效果

我们希望一个网页放到移动端的浏览器中不会影响视觉效果,然后又利于开发。所以最好的方法就是设置布局视口的宽度正好等于屏幕的大小(这里的大小是指视觉上的而不是CSS像素单位上的,意思就是比如375的屏幕宽度下,将布局视口设置为屏幕宽度,也就是device-width,CSS像素横向有375个单位,设置375px即可满屏;如果将布局视口设置为设备宽度的两倍即750px,面积增大4倍,同时设置initial-scale为0.5,面积又缩小四分之一正好又是屏幕的大小。),这样的效果就是设置100%的时候保证就是屏幕宽度。(说的比较啰嗦)

如何设置布局视口呢?

<!--设置布局视口等于device-width--><metaname="viewport"content="width=device-width"><!-- 只设置缩放值也能将布局视口宽度设置为屏幕宽度,设置为0.5时由于CSS像素缩放了0.5,填到屏幕中的CSS像素数量正好是屏幕宽度 --><metaname="viewport"content="initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no"><!-- 这是兼容写法 --><metaname="viewport"content="width=device-width,initial-scale=1, maximum-scale=1,user-scalable=no">

二、移动适配方案

移动多屏幕适配是为了保证各个屏幕上的布局视口都是等于屏幕(视觉上的)宽度。所以就有几种方案可以做到。

第一种方案

第一种方案是直接设置width=device-width,这样能够保证宽度一致,但考虑到苹果的Retina屏幕设计师出设计稿的时候都是放大了一倍设计稿,比如640px(基于iphone5)、750px(基于iphone6)。如果我们拿到的设计稿是750px宽,在设置缩放比为100%、布局视口等于屏幕宽度的情况下,我们拿到的设计稿宽度是大了一倍的,(网页中设置375px沾满屏幕,而设计稿切出的图是750px),所以在转换成网页的时候设置宽度需要将设计图的宽度除以2来,如果考虑到iphone6 plus的dpr为3,要保证在6 plus下图片还是高清,就需要将750px的设计稿再放大1.5倍,用@3倍图切出来。以上可以知道这种方案不需要动态的去根据屏幕dpr不同来设置meta标签内容,直接一句话搞定,然后需要调整的地方通过媒体查询来做。

第二种方案

第三种方案就是淘宝的flexible了。这个解决方案只解决苹果设备上的dpr为2和3的情况,不考虑安卓设备也不考虑pad。做的事情也很简单,就是动态设置meta标签的内容,和第一种方案不同的是没有设置为width=device-width,而是通过设置initial-scale来缩放布局视口,dpr为1,缩放为1;dpr为2,缩放0.5;dpr为3,缩放0.3333;通过这种方法使得布局视口在视觉上还是屏幕大小但CSS像素数量却增加了4倍/9倍。而这样的直接好处就是比如iphone6的视觉视口横向有了750个CSS像素点,和设计图保持一致了,同时CSS像素缩放0.5解决了经典的1px像素问题

该方案的核心原理是通过window.navigator.appVersion判断是否是iphone,其他的比如ipad、Android直接设置dpr为1,然后通过 1/ dpr 得到缩放值。

varisAndroid=win.navigator.appVersion.match(/android/gi);/* 判断iphone ipad不考虑*/varisIPhone=win.navigator.appVersion.match(/iphone/gi);vardevicePixelRatio=win.devicePixelRatio;if(isIPhone){// iOS下,对于2和3的屏,用2倍的方案,其余的用1倍方案if(devicePixelRatio>=3&&(!dpr||dpr>=3)){dpr=3;}elseif(devicePixelRatio>=2&&(!dpr||dpr>=2)){dpr=2;}else{dpr=1;}}else{// 其他设备下,仍旧使用1倍的方案dpr=1;}/*缩放值*/scale=1/dpr;

这个解决方案中用的布局单位是rem而不是px,这也是为了等比例缩放的问题。rem单位代表的是根节点也就是html的fontSize的值,html默认为16px,所以默认1rem = 16px。既然开发的设计标注图是750px的,将html设为75px就很方便了,10rem = 750px。

然后放到所有屏幕情况下:

functionrefreshRem(){/*获取布局视口宽度,也可用document.documentElement.clientWidth*/varwidth=document.documentElement.getBoundingClientRect().width;/* 判断屏幕宽度,如果dpr为1且宽度>540 则恒定为540px,dpr为2如果宽度>1080则恒定为1080px*/if(width/dpr>540){width=540*dpr;}/*将布局视口宽度除以10得到html字体大小*/varrem=width/10;document.documentElement.style.fontSize=rem+'px';}

比如iphone5的设备下布局视口是640,所以html的字体大小会设置为64px,而在开发的时候设置的单位为rem,这个时候rem自动根据64px转换,就实现了等比缩放。写rem的时候可以通过CSSREM插件来写,只是后期维护比较麻烦。

字体不用rem而采用px是因为我们希望一个文本字号不因为Retina显示屏的原因而缩放变小。然后在大屏上也不会放大而能够看到更多的文本。但是不同的dpr下又的确是要分别设置字号的。这个解决方案会在html元素上设置data-dpr属性,然后通过该属性判断来设置字体大小。

div.box{    font-size: 12px;}[data-dpr="2"] div{    font-size: 24px;}[data-dpr="3"] div{    font-size: 36px;}

如果觉得麻烦可以用sass来写样式,用@mixin。

设计稿设计方面要求为750px,如果设计师有做标注就做在这个稿子上,没有标注的话我们开发的时候就依据这个设计稿来量间距之类的。同时将这个稿子放大1.5倍来得到1125px的设计稿,切图用这份设计稿保证dpr为3的屏幕图片显示足够清晰。在iphone6的屏幕下开发然后再向上向下适配。字体也希望不要出现奇数值,我们都知道为什么。

viewport视口

viewport是严格的等于浏览器的窗口。viewport与跟viewport有关的meta标签的关系,详细建议读一读这篇文章:移动前端开发之viewport的深入理解,viewport与布局的关系,可以看下这篇文章:在移动浏览器中使用viewport元标签控制布局

visual viewport 可见视口 屏幕宽度

layout viewport 布局视口 DOM宽度

ideal viewport 理想适口:使布局视口就是可见视口

设备宽度(visual viewport)与DOM宽度(layout viewport), scale的关系为:

(visual viewport)= (layout viewport)* scale

获取屏幕宽度(visual viewport)的尺寸:window. innerWidth/Height。

获取DOM宽度(layout viewport)的尺寸:document. documentElement. clientWidth/Height。

设置理想视口:把默认的layout viewport的宽度设为移动设备的屏幕宽度,得到理想视口(ideal viewport):


2.替换px转而使用rem

设定父盒子的css为

父盒子{width:320px}

设置根元素的font-size为屏幕的某个比例

html{font-size:16px;}

那么父盒子的css为

父盒子{  width:20rem;//换算为320px,充满屏幕宽度height:10rem;//换算为160px,盒子比例达到1:1}

但是css的替换以及rem的计算还是比较繁琐的,这里建议使用sass的函数

然后使用正则替换

(/(\d+[\.\d+]?px)/g,'rem($1)')

$baiscRem:320px /20//这里假定为页面做20个等分@functionrem($px)@return($px / $basicRem)* 1rem父盒子width:rem(320px)

围观群众1:为什么不在写css时候直接使用rem呢?

答:每次都调尺寸都要用计算器算一下啊,好麻烦。(╯°口°)╯(┴—┴

围观群众2:为什么不直接写 rem(320px) ?

答:写括号也好麻烦。(:3」∠)

然后,使用css @media查询,确定rem的值。

这里就比较具体了,需要根据实际的业务需求来决定所要适配的设备尺寸

/* media.css */@mediascreen and (min-width:320px) and (max-width:320px){html{font-size:320/320* $basicRem;    }}@mediascreen and (min-width:400px) and (max-width:400px){html{font-size:400/320* $basicRem;    }}

tips:如果不知道要兼容什么样的设备。可以再用户访问后,javascript收集该设备的相关信息,

然后在服务端自动更新该文件的内容,加入新的@media规则。

但是全部使用rem,有个缺点很蛋疼,

就是除法导致的小数缺省的问题,导致视觉上会有几个像素的偏差。

例如:多列布局会引起几个像素的空白等 ( ̄へ ̄)

关于vw,vh

宽高的1%,建议使用在各种布局的容器上,如上图的父盒子和子盒子。

父盒子{box-sizing:border-box;padding:10vw;width:100vw;height:50vw;/* 妥妥的2:1比例 */letter-spacing: -4px;/*消除行内元素的4px的空白间隔 */}子盒子1,子盒子2{magin:05vw;width:30vw;height:30vw;/* 妥妥的1:1的比例 */display:inline-block;}

相比rem,使用vw和wh是非常直观的,让其他人看到就能知道,该界面是以怎么样的结构进行布局,利于维护。

但在具体深入到表现的地方,建议转而使用rem来配合。

注意:vw在一些三星的机子会有兼容问题,导致失效。

如果有兼容问题,vw在容器上的应用可以百分比替换 -->codepen-使用百分比实现的等比例容器

相关链接:

移动端适配方案(主要讲解的是移动端视口方面的知识): 

segmentfault.com/a/11...

segmentfault.com/a/11...

Retina屏幕下模糊的由来: 

mobile.51cto.com/web-4...

手淘flexible.js布局: 

www.w3cplus.com/mobile...

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

推荐阅读更多精彩内容