移動(dòng)和pc網(wǎng)頁布局適配多設(shè)備

一.視口(viewport)

viewport視口

viewport是嚴(yán)格的等于瀏覽器的窗口。viewport與跟viewport有關(guān)的meta標(biāo)簽的關(guān)系,詳細(xì)建議讀一讀這篇文章:移動(dòng)前端開發(fā)之viewport的深入理解,viewport與布局的關(guān)系,可以看下這篇文章:在移動(dòng)瀏覽器中使用viewport元標(biāo)簽控制布局

visual viewport?可見視口? 屏幕寬度

layout viewport?布局視口 DOM寬度

ideal viewport?理想適口:使布局視口就是可見視口

設(shè)備寬度(visual viewport)與DOM寬度(layout viewport), scale的關(guān)系為:

(visual viewport)= (layout viewport)* scale

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

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

設(shè)置理想視口:把默認(rèn)的layout viewport的寬度設(shè)為移動(dòng)設(shè)備的屏幕寬度,得到理想視口(ideal viewport):

我們進(jìn)行網(wǎng)頁布局的時(shí)候設(shè)置html元素寬度為100%,這個(gè)100%是依據(jù)什么設(shè)置的呢?瀏覽器窗口用CSS像素衡量的寬度(window.innerWidth)還是別的呢?我們可以發(fā)現(xiàn)在PC端的瀏覽器上設(shè)置100%,html元素的px寬度就等于瀏覽器寬度;而在移動(dòng)端不管是在什么設(shè)備上,html設(shè)置100%,基本上寬度都等于980px,這里的980px就是移動(dòng)端所謂的布局視口了。

在移動(dòng)端,默認(rèn)的情況下,布局視口的寬度是要遠(yuǎn)遠(yuǎn)大于瀏覽器的寬度的。這兩個(gè)視口不同于PC端,是相互獨(dú)立存在的。瀏覽器廠商為了讓用戶在小屏幕下網(wǎng)頁也能夠顯示地很好,所以把布局視口寬度設(shè)置地很大,一般在768px ~ 1024px之間,最常見的寬度是980px。這個(gè)寬度可以通過document.documentElement.clientWidth得到。

移動(dòng)端布局需要達(dá)到的效果

我們希望一個(gè)網(wǎng)頁放到移動(dòng)端的瀏覽器中不會(huì)影響視覺效果,然后又利于開發(fā)。所以最好的方法就是設(shè)置布局視口的寬度正好等于屏幕的大?。ㄟ@里的大小是指視覺上的而不是CSS像素單位上的,意思就是比如375的屏幕寬度下,將布局視口設(shè)置為屏幕寬度,也就是device-width,CSS像素橫向有375個(gè)單位,設(shè)置375px即可滿屏;如果將布局視口設(shè)置為設(shè)備寬度的兩倍即750px,面積增大4倍,同時(shí)設(shè)置initial-scale為0.5,面積又縮小四分之一正好又是屏幕的大小。),這樣的效果就是設(shè)置100%的時(shí)候保證就是屏幕寬度。(說的比較啰嗦)

如何設(shè)置布局視口呢?

<!--設(shè)置布局視口等于device-width--><metaname="viewport"content="width=device-width"><!-- 只設(shè)置縮放值也能將布局視口寬度設(shè)置為屏幕寬度,設(shè)置為0.5時(shí)由于CSS像素縮放了0.5,填到屏幕中的CSS像素?cái)?shù)量正好是屏幕寬度 --><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">

二、移動(dòng)適配方案

移動(dòng)多屏幕適配是為了保證各個(gè)屏幕上的布局視口都是等于屏幕(視覺上的)寬度。所以就有幾種方案可以做到。

第一種方案

第一種方案是直接設(shè)置width=device-width,這樣能夠保證寬度一致,但考慮到蘋果的Retina屏幕設(shè)計(jì)師出設(shè)計(jì)稿的時(shí)候都是放大了一倍設(shè)計(jì)稿,比如640px(基于iphone5)、750px(基于iphone6)。如果我們拿到的設(shè)計(jì)稿是750px寬,在設(shè)置縮放比為100%、布局視口等于屏幕寬度的情況下,我們拿到的設(shè)計(jì)稿寬度是大了一倍的,(網(wǎng)頁中設(shè)置375px沾滿屏幕,而設(shè)計(jì)稿切出的圖是750px),所以在轉(zhuǎn)換成網(wǎng)頁的時(shí)候設(shè)置寬度需要將設(shè)計(jì)圖的寬度除以2來,如果考慮到iphone6 plus的dpr為3,要保證在6 plus下圖片還是高清,就需要將750px的設(shè)計(jì)稿再放大1.5倍,用@3倍圖切出來。以上可以知道這種方案不需要?jiǎng)討B(tài)的去根據(jù)屏幕dpr不同來設(shè)置meta標(biāo)簽內(nèi)容,直接一句話搞定,然后需要調(diào)整的地方通過媒體查詢來做。

第二種方案

第三種方案就是淘寶的flexible了。這個(gè)解決方案只解決蘋果設(shè)備上的dpr為2和3的情況,不考慮安卓設(shè)備也不考慮pad。做的事情也很簡單,就是動(dòng)態(tài)設(shè)置meta標(biāo)簽的內(nèi)容,和第一種方案不同的是沒有設(shè)置為width=device-width,而是通過設(shè)置initial-scale來縮放布局視口,dpr為1,縮放為1;dpr為2,縮放0.5;dpr為3,縮放0.3333;通過這種方法使得布局視口在視覺上還是屏幕大小但CSS像素?cái)?shù)量卻增加了4倍/9倍。而這樣的直接好處就是比如iphone6的視覺視口橫向有了750個(gè)CSS像素點(diǎn),和設(shè)計(jì)圖保持一致了,同時(shí)CSS像素縮放0.5解決了經(jīng)典的1px像素問題

該方案的核心原理是通過window.navigator.appVersion判斷是否是iphone,其他的比如ipad、Android直接設(shè)置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{// 其他設(shè)備下,仍舊使用1倍的方案dpr=1;}/*縮放值*/scale=1/dpr;

這個(gè)解決方案中用的布局單位是rem而不是px,這也是為了等比例縮放的問題。rem單位代表的是根節(jié)點(diǎn)也就是html的fontSize的值,html默認(rèn)為16px,所以默認(rèn)1rem = 16px。既然開發(fā)的設(shè)計(jì)標(biāo)注圖是750px的,將html設(shè)為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的設(shè)備下布局視口是640,所以html的字體大小會(huì)設(shè)置為64px,而在開發(fā)的時(shí)候設(shè)置的單位為rem,這個(gè)時(shí)候rem自動(dòng)根據(jù)64px轉(zhuǎn)換,就實(shí)現(xiàn)了等比縮放。寫rem的時(shí)候可以通過CSSREM插件來寫,只是后期維護(hù)比較麻煩。

字體不用rem而采用px是因?yàn)槲覀兿M粋€(gè)文本字號不因?yàn)镽etina顯示屏的原因而縮放變小。然后在大屏上也不會(huì)放大而能夠看到更多的文本。但是不同的dpr下又的確是要分別設(shè)置字號的。這個(gè)解決方案會(huì)在html元素上設(shè)置data-dpr屬性,然后通過該屬性判斷來設(shè)置字體大小。

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

如果覺得麻煩可以用sass來寫樣式,用@mixin。

設(shè)計(jì)稿設(shè)計(jì)方面要求為750px,如果設(shè)計(jì)師有做標(biāo)注就做在這個(gè)稿子上,沒有標(biāo)注的話我們開發(fā)的時(shí)候就依據(jù)這個(gè)設(shè)計(jì)稿來量間距之類的。同時(shí)將這個(gè)稿子放大1.5倍來得到1125px的設(shè)計(jì)稿,切圖用這份設(shè)計(jì)稿保證dpr為3的屏幕圖片顯示足夠清晰。在iphone6的屏幕下開發(fā)然后再向上向下適配。字體也希望不要出現(xiàn)奇數(shù)值,我們都知道為什么。

viewport視口

viewport是嚴(yán)格的等于瀏覽器的窗口。viewport與跟viewport有關(guān)的meta標(biāo)簽的關(guān)系,詳細(xì)建議讀一讀這篇文章:移動(dòng)前端開發(fā)之viewport的深入理解,viewport與布局的關(guān)系,可以看下這篇文章:在移動(dòng)瀏覽器中使用viewport元標(biāo)簽控制布局

visual viewport?可見視口 屏幕寬度

layout viewport?布局視口 DOM寬度

ideal viewport?理想適口:使布局視口就是可見視口

設(shè)備寬度(visual viewport)與DOM寬度(layout viewport), scale的關(guān)系為:

(visual viewport)= (layout viewport)* scale

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

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

設(shè)置理想視口:把默認(rèn)的layout viewport的寬度設(shè)為移動(dòng)設(shè)備的屏幕寬度,得到理想視口(ideal viewport):


2.替換px轉(zhuǎn)而使用rem

設(shè)定父盒子的css為

父盒子{width:320px}

設(shè)置根元素的font-size為屏幕的某個(gè)比例

html{font-size:16px;}

那么父盒子的css為

父盒子{? width:20rem;//換算為320px,充滿屏幕寬度height:10rem;//換算為160px,盒子比例達(dá)到1:1}

但是css的替換以及rem的計(jì)算還是比較繁瑣的,這里建議使用sass的函數(shù)

然后使用正則替換

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

$baiscRem:320px /20//這里假定為頁面做20個(gè)等分@functionrem($px)@return($px / $basicRem)* 1rem父盒子width:rem(320px)

圍觀群眾1:為什么不在寫css時(shí)候直接使用rem呢?

答:每次都調(diào)尺寸都要用計(jì)算器算一下啊,好麻煩。(╯°口°)╯(┴—┴

圍觀群眾2:為什么不直接寫 rem(320px) ?

答:寫括號也好麻煩。(:3」∠)

然后,使用css @media查詢,確定rem的值。

這里就比較具體了,需要根據(jù)實(shí)際的業(yè)務(wù)需求來決定所要適配的設(shè)備尺寸

/* 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:如果不知道要兼容什么樣的設(shè)備??梢栽儆脩粼L問后,javascript收集該設(shè)備的相關(guān)信息,

然后在服務(wù)端自動(dòng)更新該文件的內(nèi)容,加入新的@media規(guī)則。

但是全部使用rem,有個(gè)缺點(diǎn)很蛋疼,

就是除法導(dǎo)致的小數(shù)缺省的問題,導(dǎo)致視覺上會(huì)有幾個(gè)像素的偏差。

例如:多列布局會(huì)引起幾個(gè)像素的空白等 ( ̄へ ̄)

關(guān)于vw,vh

寬高的1%,建議使用在各種布局的容器上,如上圖的父盒子和子盒子。

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

相比rem,使用vw和wh是非常直觀的,讓其他人看到就能知道,該界面是以怎么樣的結(jié)構(gòu)進(jìn)行布局,利于維護(hù)。

但在具體深入到表現(xiàn)的地方,建議轉(zhuǎn)而使用rem來配合。

注意:vw在一些三星的機(jī)子會(huì)有兼容問題,導(dǎo)致失效。

如果有兼容問題,vw在容器上的應(yīng)用可以百分比替換 -->codepen-使用百分比實(shí)現(xiàn)的等比例容器

相關(guān)鏈接:

移動(dòng)端適配方案(主要講解的是移動(dòng)端視口方面的知識):?

segmentfault.com/a/11...

segmentfault.com/a/11...

Retina屏幕下模糊的由來:?

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

手淘flexible.js布局:?

www.w3cplus.com/mobile...

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容