移动端适配深度探究
我在網上看過很多相關的資料,都在說淘寶適配方案和網易適配方案。說了dpr,meta等好多概念,說實話我感覺寫的都好復雜,跟我自己想的有出入。新學東西我總想找到這個東西設計的出發點,但我沒在這些文章中找出來。在看了些現在主流網站的代碼后,覺得自己有了一點心得,所以獻丑拿來分享下,希望對你有點幫助
準備
既然是適配我們開始肯定要有一個參考屏幕,這里我們先提前確定下面所有的例子都是以iphone6的屏幕(寬度為375px)為參照。通常設計稿是2倍的設計稿,所以我們拿到的設計稿設計稿最終寬度為750px。
屏幕適配
屏幕適配最終的目標或者說本質就是實現 等比縮放。
現在各大網站雖然方案有差異,但步驟和目的其實是一樣的,主要分為以下幾步:
為什么要有個基準?因為我們不希望每種屏幕寫一種布局樣式,所以我們需要有一個基準來隨屏幕寬度變化,我們只要根據基準來確定我們的css值,就可以適配所有的屏幕了。
這就是適配的全部了,下面我們來看看這幾步可以用什么方案來解決。
基準是什么?為了簡單基準我們看成單位,所以我們需要找一個能變化的單位,思考下,css中哪些單位可以變化?rem是以根字體的大小來確定自己的值的,符合條件。所以我們可以讓根字體隨屏幕變化而變化,我們直接用rem進行布局可以了。
下一步就是確定基準值,我們這里就是確定根字體的值。為了方便我們計算我們可以設置一個很容易計算的值,比如我們可以讓設計稿中1rem=100px,那么寫起來就是
// 屏幕寬度 / 7.5 = 1rem// 或// 100vw / 7.5 = 1rem 復制代碼這兩種在這個例子中是一樣的,然后我們寫樣式的時候用rem做為單位就可以了,比如設計稿上有一個寬度為80px的div元素,我們只需要這樣寫:
div {width: .8rem; } 復制代碼如果你還是嫌每次手動計算麻煩,可以用現在樣式預處理器(如less、sass)中的mixin的來幫你或者使用js來動態計算。
到這里我們的適配就說完了。你可能會問dpr、meta頭設置視圖寬度那些東西怎么沒看到,我明明在很多文章看到這些概念。別急,其實這些都是為了解決一個問題,下面我們就來說說這個問題
hairline
hairline是啥?hairline其實就是很細的線,很多設計師特別喜歡用這種線,讓我們前端頭大?。這種線直接用0.5px行嗎?這在以前一些舊的屏幕上是不行的,會被自動修正為1px,我們都知道。
但是現代很多手機都是高倍屏,即一個css像素會有多個物理像素,這樣顯示的圖像更細膩并且更清晰,有的已經支持css使用小數,這種情況下我們可以直接使用像0.5px來寫出這種寬度的線了。這里有個概念,物理像素數和css像素被稱為設備像素比,也就是我們經常說的dpr了
物理像素數 / css像素數 = dpr 復制代碼dpr的值可以通過window.devicePixelRadio來獲取。
問題好像已經解決了。但是我們前端還有很重要的一部分的工作是兼容,如果遇到不支持這種小數css寫法的怎么辦?我們想個很通用的解決方案,那就是縮放,比如我們把1px寬度的線縮小一半就能得到0.5px寬度的線了。
為了讓我們所有1px寬度縮為一個物理像素寬,我們就需要讓頁面寬度為屏幕css寬度 * dpr。然后我們在這個寬度下寫1px寬度的線,最后再縮小dpr倍我們就可以得得到1物理像素寬度了。
為了實現讓頁面變為屏幕css寬度 * dpr的寬的目的,我們需要按比例改變我們上面的適配方案。
假如現在dpr=3,我們就需要讓頁面寬度為 375 * 3 = 1125,而我們的設計稿是750。我們就需要讓我們的基準值成比例變化
// 屏幕寬度 / 7.5 => 屏幕寬度 / 7.5 / 2 * 3 復制代碼現在我們得到尺寸為屏幕css寬度 * dpr的頁面了,為了讓頁面完全顯示在屏幕中我們需要在html中設置meta頭(不了解這些的自己查下,有很多資料)
<meta name="viewport" content="width=屏幕css寬度 * dpr"> 復制代碼然后縮小dpr倍變成
<meta name="viewport" content="width=屏幕css寬度 * dpr,initial-scale=1/dpr,minimum-scale=1/dpr,maximum-scale=1/dpr,user-scalable=no"> 復制代碼到這里,我們所有東西都講完了,希望你已經理解了為什么會有那么多寫法不同的適配方案了,他們都是殊途同歸。
思考題
最后附上現在淘寶和網易的部分代碼,你可以自己直接去他們網站找到這些代碼。你應該能根據這些代碼分析他們的方案了,這些留給你自己思考和分析了
手機淘寶網部分適配代碼
! function (e, t) {var n = t.documentElement,d = e.devicePixelRatio || 1;function i() {var e = n.clientWidth / 3.75;n.style.fontSize = e + "px"}if (function e() {t.body ? t.body.style.fontSize = "16px" : t.addEventListener("DOMContentLoaded", e)}(), i(), e.addEventListener("resize", i), e.addEventListener("pageshow", function (e) {e.persisted && i()}), 2 <= d) {var o = t.createElement("body"),a = t.createElement("div");a.style.border = ".5px solid transparent", o.appendChild(a), n.appendChild(o), 1 === a.offsetHeight && n.classList.add("hairlines"), n.removeChild(o)} }(window, document) 復制代碼手機網易新聞網部分適配代碼
html {font-size: 13.33333vw }@media screen and (max-width: 320px) {html {font-size:42.667px;font-size: 13.33333vw} }@media screen and (min-width: 321px) and (max-width:360px) {html {font-size:48px;font-size: 13.33333vw} }@media screen and (min-width: 361px) and (max-width:375px) {html {font-size:50px;font-size: 13.33333vw} }@media screen and (min-width: 376px) and (max-width:393px) {html {font-size:52.4px;font-size: 13.33333vw} }@media screen and (min-width: 394px) and (max-width:412px) {html {font-size:54.93px;font-size: 13.33333vw} }@media screen and (min-width: 413px) and (max-width:414px) {html {font-size:55.2px;font-size: 13.33333vw} }@media screen and (min-width: 415px) and (max-width:480px) {html {font-size:64px;font-size: 13.33333vw} }@media screen and (min-width: 481px) and (max-width:540px) {html {font-size:72px;font-size: 13.33333vw} }@media screen and (min-width: 541px) and (max-width:640px) {html {font-size:85.33px;font-size: 13.33333vw} }@media screen and (min-width: 641px) and (max-width:720px) {html {font-size:96px;font-size: 13.33333vw} }@media screen and (min-width: 721px) and (max-width:768px) {html {font-size:102.4px;font-size: 13.33333vw} }@media screen and (min-width: 769px) {html {font-size:102.4px;font-size: 13.33333vw} } 復制代碼本文原文更新在我的github上,這里是原文鏈接。如果文章有任何錯誤或不準確之處,歡迎指出,非常感謝!
轉載于:https://juejin.im/post/5c9830e65188252d64583343
總結
- 上一篇: Docker版本(三)
- 下一篇: jQuery.parseJSON()函数