一.視口(viewport)
viewport視口
viewport是嚴格的等于瀏覽器的窗口趾浅。viewport與跟viewport有關(guān)的meta標簽的關(guān)系,詳細建議讀一讀這篇文章:移動前端開發(fā)之viewport的深入理解饱狂,viewport與布局的關(guān)系揪罕,可以看下這篇文章:在移動瀏覽器中使用viewport元標簽控制布局
visual viewport?可見視口? 屏幕寬度
layout viewport?布局視口 DOM寬度
ideal viewport?理想適口:使布局視口就是可見視口
設備寬度(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歇攻。
設置理想視口:把默認的layout viewport的寬度設為移動設備的屏幕寬度译隘,得到理想視口(ideal viewport):
我們進行網(wǎng)頁布局的時候設置html元素寬度為100%,這個100%是依據(jù)什么設置的呢洛心?瀏覽器窗口用CSS像素衡量的寬度(window.innerWidth)還是別的呢固耘?我們可以發(fā)現(xiàn)在PC端的瀏覽器上設置100%,html元素的px寬度就等于瀏覽器寬度词身;而在移動端不管是在什么設備上厅目,html設置100%,基本上寬度都等于980px法严,這里的980px就是移動端所謂的布局視口了损敷。
在移動端,默認的情況下渐夸,布局視口的寬度是要遠遠大于瀏覽器的寬度的。這兩個視口不同于PC端渔欢,是相互獨立存在的墓塌。瀏覽器廠商為了讓用戶在小屏幕下網(wǎng)頁也能夠顯示地很好,所以把布局視口寬度設置地很大奥额,一般在768px ~ 1024px之間苫幢,最常見的寬度是980px。這個寬度可以通過document.documentElement.clientWidth得到垫挨。
移動端布局需要達到的效果
我們希望一個網(wǎng)頁放到移動端的瀏覽器中不會影響視覺效果韩肝,然后又利于開發(fā)。所以最好的方法就是設置布局視口的寬度正好等于屏幕的大芯爬啤(這里的大小是指視覺上的而不是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像素數(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">
二刺彩、移動適配方案
移動多屏幕適配是為了保證各個屏幕上的布局視口都是等于屏幕(視覺上的)寬度涮拗。所以就有幾種方案可以做到乾戏。
第一種方案
第一種方案是直接設置width=device-width,這樣能夠保證寬度一致三热,但考慮到蘋果的Retina屏幕設計師出設計稿的時候都是放大了一倍設計稿鼓择,比如640px(基于iphone5)、750px(基于iphone6)就漾。如果我們拿到的設計稿是750px寬呐能,在設置縮放比為100%、布局視口等于屏幕寬度的情況下抑堡,我們拿到的設計稿寬度是大了一倍的摆出,(網(wǎng)頁中設置375px沾滿屏幕,而設計稿切出的圖是750px)首妖,所以在轉(zhuǎn)換成網(wǎng)頁的時候設置寬度需要將設計圖的寬度除以2來偎漫,如果考慮到iphone6 plus的dpr為3,要保證在6 plus下圖片還是高清有缆,就需要將750px的設計稿再放大1.5倍象踊,用@3倍圖切出來。以上可以知道這種方案不需要動態(tài)的去根據(jù)屏幕dpr不同來設置meta標簽內(nèi)容棚壁,直接一句話搞定杯矩,然后需要調(diào)整的地方通過媒體查詢來做。
第二種方案
第三種方案就是淘寶的flexible了袖外。這個解決方案只解決蘋果設備上的dpr為2和3的情況史隆,不考慮安卓設備也不考慮pad。做的事情也很簡單曼验,就是動態(tài)設置meta標簽的內(nèi)容泌射,和第一種方案不同的是沒有設置為width=device-width,而是通過設置initial-scale來縮放布局視口,dpr為1鬓照,縮放為1魄幕;dpr為2,縮放0.5颖杏;dpr為3纯陨,縮放0.3333;通過這種方法使得布局視口在視覺上還是屏幕大小但CSS像素數(shù)量卻增加了4倍/9倍留储。而這樣的直接好處就是比如iphone6的視覺視口橫向有了750個CSS像素點翼抠,和設計圖保持一致了,同時CSS像素縮放0.5解決了經(jīng)典的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單位代表的是根節(jié)點也就是html的fontSize的值滞详,html默認為16px,所以默認1rem = 16px紊馏。既然開發(fā)的設計標注圖是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栋猖,而在開發(fā)的時候設置的單位為rem,這個時候rem自動根據(jù)64px轉(zhuǎn)換瓣戚,就實現(xiàn)了等比縮放让腹。寫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,如果設計師有做標注就做在這個稿子上脐区,沒有標注的話我們開發(fā)的時候就依據(jù)這個設計稿來量間距之類的愈诚。同時將這個稿子放大1.5倍來得到1125px的設計稿,切圖用這份設計稿保證dpr為3的屏幕圖片顯示足夠清晰牛隅。在iphone6的屏幕下開發(fā)然后再向上向下適配炕柔。字體也希望不要出現(xiàn)奇數(shù)值,我們都知道為什么媒佣。
viewport視口
viewport是嚴格的等于瀏覽器的窗口匕累。viewport與跟viewport有關(guān)的meta標簽的關(guān)系,詳細建議讀一讀這篇文章:移動前端開發(fā)之viewport的深入理解默伍,viewport與布局的關(guān)系欢嘿,可以看下這篇文章:在移動瀏覽器中使用viewport元標簽控制布局
visual viewport?可見視口 屏幕寬度
layout viewport?布局視口 DOM寬度
ideal viewport?理想適口:使布局視口就是可見視口
設備寬度(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。
設置理想視口:把默認的layout viewport的寬度設為移動設備的屏幕寬度炼蹦,得到理想視口(ideal viewport):
2.替換px轉(zhuǎn)而使用rem
設定父盒子的css為
父盒子{width:320px}
設置根元素的font-size為屏幕的某個比例
html{font-size:16px;}
那么父盒子的css為
父盒子{? width:20rem;//換算為320px羡宙,充滿屏幕寬度height:10rem;//換算為160px,盒子比例達到1:1}
但是css的替換以及rem的計算還是比較繁瑣的框弛,這里建議使用sass的函數(shù)
然后使用正則替換
(/(\d+[\.\d+]?px)/g,'rem($1)')
$baiscRem:320px /20//這里假定為頁面做20個等分@functionrem($px)@return($px / $basicRem)* 1rem父盒子width:rem(320px)
圍觀群眾1:為什么不在寫css時候直接使用rem呢辛辨?
答:每次都調(diào)尺寸都要用計算器算一下啊,好麻煩瑟枫。(╯°口°)╯(┴—┴
圍觀群眾2:為什么不直接寫 rem(320px) 斗搞?
答:寫括號也好麻煩。(:3」∠)
然后慷妙,使用css @media查詢僻焚,確定rem的值。
這里就比較具體了膝擂,需要根據(jù)實際的業(yè)務需求來決定所要適配的設備尺寸
/* 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收集該設備的相關(guān)信息狞山,
然后在服務端自動更新該文件的內(nèi)容,加入新的@media規(guī)則叉寂。
但是全部使用rem萍启,有個缺點很蛋疼,
就是除法導致的小數(shù)缺省的問題屏鳍,導致視覺上會有幾個像素的偏差勘纯。
例如:多列布局會引起幾個像素的空白等 ( ̄へ ̄)
關(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)進行布局鸭丛,利于維護竞穷。
但在具體深入到表現(xiàn)的地方,建議轉(zhuǎn)而使用rem來配合系吩。
注意:vw在一些三星的機子會有兼容問題来庭,導致失效。
如果有兼容問題,vw在容器上的應用可以百分比替換 -->codepen-使用百分比實現(xiàn)的等比例容器
相關(guān)鏈接:
移動端適配方案(主要講解的是移動端視口方面的知識):?
Retina屏幕下模糊的由來:?
手淘flexible.js布局:?