當我們在項目開發中,拿到設計師的設計圖,滿懷欣喜的准備按照設計圖將頁面實現出來的時候,我們通常會遇到這個問題:
如何將頁面的內容按照在不同手機屏幕瀏覽的情況下,比例都是不變的呢?這個時候我們就需要使用到動態rem來解決問題。
1:拿到屏幕寬度,以屏幕寬度作為rem的基准值
2:如果覺得基准值過大,將px換算成rem比較麻煩,可以將基准值縮小10倍
3:因谷歌瀏覽器有一個最小字體值,所以基准值不要低於這個最小字體值(12px)。
4:將rem賦值給html
var width = window.screen.width var fontSize = width/10 + 'px' document.getElementsByTagName('html')[0].style.fontSize = fontSize
當我們在寫頁面的時候設計師會提出這樣一個要求:頁面不管怎么縮放都可以,但是1px的邊框必須給我是1px,不能縮放。我們會覺得這個問題很奇葩,心里想大不了直接給border:1px不就行了。可這個時候設計師又會說:我要的是手機上的實際像素1px!!!
真是有句mmp不知當講不當講。
好,既然需求說了,我們總不能說勞資不干了吧。那這個時候就需要了解到這個知識點:何為retina屏幕?啥是dpr?靈魂畫師上圖說話:
我們可以發現,在同樣的大小下,2dpr的屏幕時普通屏幕像素點的4倍,3dpr的屏幕時普通屏幕像素點的9倍。這就是retina屏幕用了都說好的原因(清晰)。而設計師要的實際1px的邊框就是下面這種情況:
這下我們終於明白設計師要的是啥效果了,那我們怎么解決呢?
思路:我們將border設置為1px,然后將也頁面的整體根據頁面的dpr縮小相應的倍數,接着將rem補償相應的倍數,這樣頁面中只有1px的邊框縮小了,而其他內容經過縮小和擴大,還是原來的狀態。
1:獲取dpr的值:
var dpr = window.devicePixelRatio
2:頁面縮放相應的倍數:
注意:頁面中<meta name="viewport"......只能作用一次,所以只能用js插入。記住content="width=device-width"千萬不要加,不然就不會縮放了(因為這句話的意思是寬度等與設備寬度)
var scale = 1/dpr var metaEle = document.getElementById("meta") metaEle.setAttribute("content",'user-scalable=no, initial-scale='+scale+', maximum-scale='+scale+', minimum-scale='+scale)
最后我們全部代碼貼上:
var width = window.screen.width var dpr = window.devicePixelRatio var scale = 1/dpr var fontSize = width/10*dpr + 'px' document.getElementsByTagName('html')[0].style.fontSize = fontSize var metaEle = document.getElementById("metaEle") //這個是meta元素 metaEle.setAttribute("content",'user-scalable=no, initial-scale='+scale+', maximum-scale='+scale+', minimum-scale='+scale)
這樣,我們就可以將頁面中需要加寬高的元素,換算成rem就行啦。
如:iphone5中,1rem = 64px;那我們頁面中某個寬高為128px和64px的元素需,設置為width=2rem;height=1rem就可以啦。
2017/9/18更新:
在閱讀大漠老師的文章后,發現這個之前的方法還是有不足之處(僅作用於dpr為整數,並且viewport為360,720或1080),所以將代碼改為如下方式,其具體代表的意思請參考:傳送門
metaEl.setAttribute('content', 'target-densitydpi=device-dpi,user-scalable=no,initial-scale=' + scale + ',maximum-scale=' + scale + ', minimum-scale=' + scale); //不通過加入具體設備的白名單,通過此特征檢測 docEl.clientWidth == 980 //initial-scale=1不能省,因為上面設置為其他的scale了,需要重置回來 if(docEl.clientWidth == 980) { metaEl.setAttribute('content', 'target-densitydpi=device-dpi,width=device-width,user-scalable=no,initial-scale=1,maximum-scale=1,minimum-scale=1'); }