基本一直都在做移動端的開發,rem布局也寫了很久,不過對于實現的原理有些模棱兩可的盲點,自己總結一下留著以后回顧。 本文分以下幾個層面,主打用最最通俗的語言來闡述。
- 布局小例子
- viewport作用
- viewport和移動端適配的關系
- flexible.js原理
- vw vh
- flexible.js VS vw vh
布局小例子----常見困惑
iphone6尺寸是375*667,那給div設置寬度375px后,為什么寬度不是充滿屏幕呢? 代碼如下:(為了方面看,我全截圖吧)
這是為什么呢? 來看一下頁面寬度是多少
viewport作用
viewport是什么?翻譯過來就是視窗的意思,只不過在移動端,視窗稍微有點繞。在解釋這個之前,不得不引出幾個詞匯,分別是物理像素(physical pixel),設備獨立像素(density-indenpendent pixel),設備像素比(device pixel ratio),要怎么通俗理解這三個詞呢? 容我找找網上的圖。
物理像素
手機屏幕顯示圖像的最小單元。上圖中iphone4和3gs,同樣大小尺寸情況下,iphone4明顯畫面細膩很多,這是為什么?屏幕尺寸沒變,分辨率提升,畫面就細膩了,更通俗一點的就是iphone4用來顯示圖像的點更多了,把屏幕上的物理像素點想象成整齊排列的點陣,3gs有320 * 480個點而ip4有960 * 640個點。
設備獨立像素
如果把物理像素看做是負責顯示圖像的硬件的話,那么設備獨立像素是什么呢?我們平時寫的css像素就是設備獨立像素的一種了。而這1px的css像素,在不同的手機卻是呈現不同的,為什么ip4畫面細膩?就是人家用4個物理像素點來描繪一個css像素。
設備像素比
也就是常說的dpr , dpr = 物理像素/設備獨立像素(注意,是在某一方向的,x軸或者y軸) , 理解這個很重要,iphone6的dpr是2,iphonex的dpr是3。
dpr是2的情況下css畫一個點,這個點是由4個物理像素點提供支撐的。畫一條線的話,那這條線其實是2排物理像素點支撐的。
同理,dpr是3的情況下css畫一個點,這個點是由9個物理像素點提供支撐的。畫一條線的話,那這條線其實是3排物理像素點支撐的。
viewport登場
在移動端,視窗分為三種,分別為layoutviewport、visualviewport、idealviewport。可以先記住一個,idealviewport就認為是設備寬度就好,iphone6就是375,iphone6p 就是414 ,其余兩個先看我下面例子吧。
window.devicePixelRatio : 查看設備dpr
document.documentElement.clientWidth : 查看layoutviewport寬度
window.visualViewport.width : 查看visualViewport寬度
window.innerWidth : 查看文檔寬度
需要來個小結了:
layoutviewport
默認是980 (針對ios)
設置縮放為1 寬度為設備寬度時:就是375(設備寬度)
設置縮放為2 寬度為設備寬度時:還是375(設備寬度)
設置縮放為0.5 寬度為設備寬度時:是750(設備寬度的2倍)
layoutviewport 取設置的寬度或者visualviewport他們中的最大值
visualviewport
默認是980 (針對ios)
設置縮放為1 寬度為設備寬度時:就是375(設備寬度)
設置縮放為2 寬度為設備寬度時:是187.5(設備寬度一半)
設置縮放為0.5 寬度為設備寬度時:是750(設備寬度的2倍)
其實是有公式的,visualviewport = 設備寬度/縮放。也就是visualviewport = idealviewport / initial-scale
idealviewport
顧名思義,是理想視窗意思,就是指的設備尺寸,主要用來和initial-scale配合,計算也就是visualviewport用的。
那layoutviewport和visualviewport負責什么
其實也是可以從名字就看出來的,layoutviewport布局視窗,visualviewport視覺視窗。 這里加個圖,initial-scale = 1 width=devide-width,然后box寬度設置750px,發現html寬度在375,頁面出現滾動條,并且,有意思的是,是按照375寬度排列的,只有那個設置了寬度是750的box寬度變大,所以layoutviewport負責布局,visualviewport負責視覺,是不是有了點直觀印象了,如下圖:
viewport和移動端適配關系
這里就更不好用語言描述了,有些抽象。回顧上文,知道iphone3gs iphone6 iphonex三者屏幕尺寸大小不同,dpr的話,前兩者是1 2 而 iphonex是3。那如何使得一張前端頁面,在每個手機看起來都是一樣大呢?以iphone6和iphonex來舉例,雖然屏幕寬度都是375,但是iphonex卻擁有更加密集的物理像素點陣。iphone3gs更不用說,320的寬度,dpr又是1。 倘若我們規定,只用設備的物理像素,來繪制css的像素,要求一比一的繪制,那一張320px寬度的頁面,在3個手機上的展示一定大致如下:
這只是一個示意圖,也許并不精準。不過大體就是這樣的,ip6寬度有著750個物理像素點,iphonex寬度有1125個物理像素點,所以根據上面的假想要求,畫出來的一定是這樣的。那么想要iphone6畫出的這個320px的頁面也充滿屏幕的話,要怎么做?首先假如設置initial-scale=1, width=device-width,這種情況下,寬度375的iphone6畫出寬度320px的前端頁面大致什么樣呢?
rem適配方案
rem是什么,這個大家應該都清楚了。就是給html設置字體大小,假如是30px,那么頁面中寫了2rem那就是60px。 設計給出一張設計稿,頁面寬度是750px,其中一個div標注了是寬度375px。如何做到在iphone6和iphonex中,看到的這個div都是屏幕寬度的一半呢?
相信大家都已經有答案了。
對于iphone6 設置initial-scale=0.5, width=device-width,然后就直接寫375px就好 對于iphonex 設置initial-scale=1/3, width=device-width,然后就直接寫(375*(3/2))px就好。 缺點就是需要我們自行計算。
rem方案 : 設計稿750px,div標注375px,對于iphone6 設置initial-scale=0.5, width=device-width,如果html設置font-size為75px,那div我們就直接寫5rem就行了。然后適配到iphonex中時,不需要改變div的5rem,只需改變在iphonex中html的字體以及頁面縮放,設置 iphonex中 initial-scale=1/3, width=device-width,然后設置html字體為112.5px,此時的5rem為562.5px,剛好是屏幕1125的一半。
flexible.js原理
上面關于rem適配已經思路實現,現在還差幾個環節,就是為什么設置iphone6是0.5縮放,iphonex是1/3縮放呢?然后又根據什么設置的html字體?
答: dpr 。那么又是怎么設置的?flexible.js就要登場了,flexible.js是手淘的前移動端適配解決方案,為什么是前方案,因為目前瀏覽器對于vw vh支持的更加友好,這個后面再說。看看flexible.js做了什么吧,直接截圖一些代碼吧。
感覺沒什么好解釋的,就是獲取設備dpr,然后確定scale嘛
然后把meta標簽塞到html中
不過rem我們自己來計算的話就很繁瑣了,如給的iphone6,寬度750的設計稿,標注的375px,我們就寫375px就好,當然是寫成px2rem(375)這樣。
關于flexible.js的實現原理,我也就是挑重點的說了說,還是建議大家去看大漠老師寫的源碼,一百多行代碼而已,挺好的,也很容易看懂,不過要想清楚為什么要那么做,就是我上面大篇幅寫的東東啦~
vw vh
關于vw vh其實是將視口寬度 window.innerWidth 和視口高度 window.innerHeight 等分為 100 份,并且此時的視窗并不會隨著 viewport 的不同設置而改變。
vw : 1vw 為視口寬度的 1%
vh : 1vh 為視口高度的 1%
上面說的設計稿為 750px,那么 1vw = 7.5px,100vw = 750px。此時給的不是750設計稿也沒所謂,假如給1000px的設計稿,那我們寫的1v我就是10px。其實這不就是rem做的事嗎?只不過我們用rem+flexible.js繞了一圈的感覺
后面具體項目中新頁面用vw試試,有什么坑 待補充
flexible.js VS vw vh
作為后面要補充的點吧,vw等我項目具體實操一波,再來補這個