## 一篇搞定移動端適配
[前端大全](javascript:void(0);)*3月23日*
以下文章來源于前端工匠,作者好學習吧丶
[

**前端工匠**
我是浪里行舟,Github博客4500+star作者,掘金、CSDN社區活躍作者,致力于打造一系列能夠幫助前端工程師提高的優質文章。
](https://mp.weixin.qq.com/s/ysPmhr0zwscxPE3Q_xtY3w#)
(給前端大全加星標,提升前端技能)
> 作者:好學習吧丶
>
> https://juejin.im/post/5e6caf55e51d4526ff026a71
## 前言
手機市場日漸豐富的同時,給我們前端開發人員帶來的 “網頁內容自適應屏幕尺寸進行顯示的問題” 也日漸凸顯出來,接下來我們就要細說移動端適配的前世今生及方案。
## 一、為什么要移動端適配?
> 一般情況下設計稿的設計師按照 375 的尺寸設計,然而,在現在移動終端(就是手機)快速更新的時代,每個品牌的手機都有著不同的物理分辨率,這樣就會導致,每臺設備的邏輯分辨率也不盡相同,此時 375 的設計稿,如果想要還原那基本是不可能了,因為如果一個左右布局,左邊如果寫死,右邊自適應的話,每個設備的右邊所展示的內容大小就不盡相同,這時移動端適配就顯得尤其重要。
既然要了解前世今生,我們就從幾個概念說起,先上一張圖。

下面我們一個個解析
### 1.1 屏幕尺寸
> 屏幕尺寸是以屏幕對角線的長度來計量,計量單位為英寸。
如圖所示兩個對角線的長度就是這個屏幕的尺寸

### 1.2 像素
我們看到上圖 320x480 叫分辨率,而這個所謂的分辨率說白了就是橫向320個像素縱向480個像素組成?
1.2.1 什么叫像素呢?
> 像素(Pel, pixel, pictureelement),為組成一幅圖像的全部亮度和色度的最小圖像單元。電視的圖像是由按一定間隔排列的亮度不同的像點構成的,形成像點的單位也就是像素,組成圖像的最小單位就是像素。從計算機技術的角度來解釋,像素是硬件和軟件所能控制的最小單位。它指顯示屏的畫面上表示出來的最小單位,不是圖畫上的最小單位。一幅圖像通常包含成千上萬個像素,每個像素都有自己的顏色信息,它們緊密地組合在一起。由于人眼的錯覺,這些組合在一起的像素被當成一幅完整的圖像。當修改圖像的某區域,實際上是在修改該區域內的像素。對這些像素修改的好與壞將決定最終圖片的質量。單位面積內的像素越多,圖像的效果就越好。彩色電視圖像是由成千個像素點所組成的,而且每個像素都是由紅綠藍三種顏色并排組成的。(**注意每個像素的大小是不固定的,他是根據設備的分辨率決定的,知識點,后面要考**)
#### 1.2.2 什么叫分辨率呢?
> 屏幕分辨率是指縱橫向上的像素點數,單位是 px。屏幕分辨率確定計算機屏幕上顯示多少信息的設置,以水平和垂直像素來衡量。就相同大小的屏幕而言,當屏幕分辨率低時(例如 640 x 480),在屏幕上顯示的像素少,單個像素尺寸比較大。屏幕分辨率高時(例如 1600 x 1200),在屏幕上顯示的像素多,單個像素尺寸比較小。
知道什么叫做分辨率后,有人就會奇怪,我記得蘋果的蘋果官網上的蘋果 6 的分辨率為 750x1334 啊,但是設計稿上蘋果 6 的分辨率為 375x667 啊,而且各個設備的分辨率都比實際分辨率小很多,這就牽扯到一些歷史原因了
#### 1.2.3 設備物理分辨率(設備像素)
相信我們所有前端開發者,都是見證了手機這個移動設備發展的過程。從藍屏手機,到彩屏手機,到諾基亞研發出來觸屏手機,再到智能手機一步步發展下來,我們的我們的手越來越清晰,越來越大,所以我們的屏幕發展也越來越迅速。

上圖可以清楚的看到,不同分辨率所帶來的的差距
從最初的顆粒感相當大的屏幕,到 720p 再到 1080p,甚至于現在各家旗艦手機的 2k 屏幕,我們的物理分辨率在變得原來越大。這樣就暴露出來一個問題,我們如果手機分辨率翻倍,我們的圖像不就要被縮小一倍,我們難道要在每個設備上就出個設計稿,每個設備的分辨不盡相同啊,其實你擔憂的問題,我們的喬幫主在很多年前就想到了。這就是我們的邏輯分辨率
#### 1.2.4 邏輯分辨率(設備獨立像素)
如下圖所示,雖然設備物理分辨不同,但是他的這個邏輯分辨率卻都差不多,這就要感謝喬幫主了。

喬布斯在 iPhone4 的發布會上首次提出了 Retina Display(視網膜屏幕)的概念,在 iPhone4 使用的視網膜屏幕中,把 2x2 個像素當 1 個像素使用,這樣讓屏幕看起來更精致,但是元素的大小卻不會改變。從此以后高分辨率的設備,多了一個邏輯像素。這些設備邏輯像素的差別雖然不會跨度很大,但是仍然有點差別,于是便誕生了移動端頁面需要適配這個問題,既然邏輯像素由物理像素得來,那他們就會有一個像素比值。
#### 1.2.5 設備像素比
設備像素比 device pixel ratio 簡稱 dpr,即物理像素和設備獨立像素的比值。為什么要知道設備像素比呢?因為這個像素比會產生一個非常經典的問題,1 像素邊框的問題。
1. 1px 邊框問題
> 當我們 css 里寫的 1px 的時候,由于它是邏輯像素,導致我們的邏輯像素根據這個設備像素比(dpr)去映射到設備上就為 2px,或者 3px,由于每個設備的屏幕尺寸不一樣,就導致每個物理像素渲染出來的大小也不同(記得上面的知識點嗎,設備的像素大小是不固定的),這樣如果在尺寸比較大的設備上,1px 渲染出來的樣子相當的粗礦,這就是經典的一像素邊框問題。
2. 如何解決
核心思路,就是**在 web 中,瀏覽器為我們提供了 window.devicePixelRatio 來幫助我們獲取 dpr。在 css 中,可以使用媒體查詢 min-device-pixel-ratio,區分 dpr:**我們根據這個像素比,來算出他對應應該有的大小,但是暴露個非常大的兼容問題。

> 其中 Chrome 把 0.5px 四舍五入變成了 1px,而 firefox/safari 能夠畫出半個像素的邊,并且 Chrome 會把小于 0.5px 的當成 0,而 Firefox 會把不小于 0.55px 當成 1px,Safari 是把不小于 0.75px 當成 1px,進一步在手機上觀察 iOS 的 Chrome 會畫出 0.5px 的邊,而安卓(5.0)原生瀏覽器是不行的。所以直接設置 0.5px 不同瀏覽器的差異比較大,并且我們看到不同系統的不同瀏覽器對小數點的 px 有不同的處理。**所以如果我們把單位設置成小數的 px 包括寬高等,其實不太可靠,因為不同瀏覽器表現不一樣**。
至于其他解決一像素邊框問題網上有一堆答案,在這里我推薦一種非常好用,并且沒有副作用的解決方案。
**transform: scale(0.5) 方案**
~~~
div { height:1px; background:#000; -webkit-transform: scaleY(0.5); -webkit-transform-origin:00; overflow: hidden;}
~~~
css 根據設備像素比媒體查詢后的解決方案
~~~
/* 2倍屏 */@media only screen and (-webkit-min-device-pixel-ratio: 2.0) { .border-bottom::after { -webkit-transform: scaleY(0.5); transform: scaleY(0.5); }}/* 3倍屏 */@media only screen and (-webkit-min-device-pixel-ratio: 3.0) { .border-bottom::after { -webkit-transform: scaleY(0.33); transform: scaleY(0.33); }}
~~~
如此,完美的解決一像素看著粗的問題。
> **擴展補充**
>
> CSS 最新的規范中正在計劃通過標準的屬性實現一像素邊框,通過給`border-width`屬性添加`hairline`關鍵字屬性來實現,具體如下鏈接\[1\]。之所以叫hairline,是因為一像素邊框就跟頭發絲一樣。
>
> 練習使用方案時,也要多多關注最新發展喲。
## 二、如何適配
### 2.1 viewport
> 視口(viewport)代表當前可見的計算機圖形區域。在 Web 瀏覽器術語中,通常與瀏覽器窗口相同,但不包括瀏覽器的 UI, 菜單欄等——即指你正在瀏覽的文檔的那一部分。
那么在移動端如何配置視口呢?簡單的一個 meta 標簽即可!
~~~
<meta name="viewport" content="width=device-width; initial-scale=1; maximum-scale=1; minimum-scale=1; user-scalable=no;">
~~~
他們分別什么含義呢?

我們在移動端視口要想視覺效果和體驗好,那么我們的視口寬度必須無限接近理想視口。
**理想視口:一般來講,這個視口其實不是真是存在的,它對設備來說是一個最理想布局視口尺寸,在用戶不進行手動縮放的情況下,可以將頁面理想地展示。那么所謂的理想寬度就是瀏覽器(屏幕)的寬度了。**
于是上述的 meta 設置,就是我們的理想設置,他規定了我們的視口寬度為屏幕寬度,初始縮放比例為 1,就是初始時候我們的視覺視口就是理想視口!
**其中 user-scalable 設置為 no 可以解決移動端點擊事件延遲問題**(拓展)
### 2.2 適配方法
#### 2.2.1 rem 適配
> rem 是 CSS3 新增的一個相對單位,這個單位引起了廣泛關注。這個單位與 em 有什么區別呢?區別在于使用 rem 為元素設定字體大小時,仍然是相對大小,但相對的只是 HTML 根元素。這個單位可謂集相對大小和絕對大小的優點于一身,通過它既可以做到只修改根元素就成比例地調整所有字體大小,又可以避免字體大小逐層復合的連鎖反應。目前,除了 IE8 及更早版本外,所有瀏覽器均已支持 rem。對于不支持它的瀏覽器,應對方法也很簡單,就是多寫一個絕對單位的聲明。這些瀏覽器會忽略用 rem 設定的字體大小。
舉個例子:
~~~
//假設我給根元素的大小設置為14pxhtml{ font-size:14px}//那么我底下的p標簽如果想要也是14像素p{ font-size:1rem}//如此即可
~~~
rem 的布局,不得不提 flexible,flexible 方案是阿里早期開源的一個移動端適配解決方案,引用 flexible 后,我們在頁面上統一使用 rem 來布局。
他的原理非常簡單
~~~
// set 1rem = viewWidth / 10function setRemUnit () { var rem = docEl.clientWidth / 10 docEl.style.fontSize = rem + 'px'}setRemUnit();
~~~
rem 是相對于 html 節點的 font-size 來做計算的。所以在頁面初始話的時候給根元素設置一個 font-size,接下來的元素就根據 rem 來布局,這樣就可以保證在頁面大小變化時,布局可以自適應。
如此我們只需要給設計稿的 px 轉換成對應的 rem 單位即可。
當然,這個方案只是個過渡方案,為什么說是過渡方案
因為當年 viewport 在低版本安卓設備上還有兼容問題,而 vw,vh 還沒能實現所有瀏覽器兼容,所以 flexible 方案用 rem 來模擬 vmin 來實現在不同設備等比縮放的“過度”方案,之所以說是過度方案,是因為這個他這個根據設備大小去判斷頁面的方案是根據屏幕大小去百分百還原設計稿,從而讓人看到的大小效果是一樣的,但是 蘋果 5 和蘋果 6p 雖然看到的設計稿還原是一樣的,但是他在一個合適距離上看到的效果能一樣嗎,本質上,**用戶使用更大的屏幕,是想看到更多的內容,而不是更大的字。**
so,這個用縮放來解決問題的方案是個過渡方案,注定被時代所淘汰。
#### 2.2.2 vw,vh 布局
> vh、vw 方案即將視覺視口寬度 window.innerWidth 和視覺視口高度 window.innerHeight 等分為 100 份。

vh 和 vw 方案和 rem 類似也是相當麻煩需要做單位轉化,而且 px 轉換成 vw 不一定能完全整除,因此有一定的像素差。
不過在工程化的今天,webpack 解析 css 的時候用 postcss-loader 有個 postcss-px-to-viewport 能自動實現 px 到 vw 的轉化
~~~
{ loader: 'postcss-loader', options: { plugins: ()=>[ require('autoprefixer')({ browsers: ['last 5 versions'] }), require('postcss-px-to-viewport')({ viewportWidth: 375, //視口寬度(數字) viewportHeight: 1334, //視口高度(數字) unitPrecision: 3, //設置的保留小數位數(數字) viewportUnit: 'vw', //設置要轉換的單位(字符串) selectorBlackList: ['.ignore', '.hairlines'], //不需要進行轉換的類名(數組) minPixelValue: 1, //設置要替換的最小像素值(數字) mediaQuery: false//允許在媒體查詢中轉換px(true/false) }) ]}
~~~
#### 2.2.3 px 為主,vx 和 vxxx(vw/vh/vmax/vmin)為輔,搭配一些 flex(推薦)
之所以推薦使用此種方案,是由于我們要去考慮用戶的需求,**用戶之所以去買大屏手機,不是為了看到更大的字,而是為了看到更多的內容**,這樣直接使用 px 是最明智的方案,使用 vw,rem 等布局手段無可厚非,但是,flex 這種彈性布局大行其道的今天,如果如果還用這種傳統的思維去想問題顯然是有兩個原因(個人認為 px 是最好的,可能有大佬,能用 vw,或者 rem 寫出精妙的布局,也說不準)。
1. **為了偷懶,不愿意去做每個手機的適**
2. **不愿意去學習新的布局方式,讓 flex 等先進的布局和你擦肩而過**
### 2.3 移動端適配流程
**1\. 在 head 設置 width=device-width 的 viewport**‘
**2\. 在 css 中使用 px**
**3\. 在適當的場景使用 flex 布局,或者配合 vw 進行自適應**
**4\. 在跨設備類型的時候(pc 手機 平板)使用媒體查詢**
**5\. 在跨設備類型如果交互差異太大的情況,考慮分開項目開發**
## 寫在最后
疫情期間有了跳槽的想法,問到移動端布局方面,雖然勉強能回答上來,但是總是支支吾吾,不是很了解,故而,發下宏愿,梳理移動端適配,幫助后來人后來者居上!
### 參考資料
\[1\]
鏈接:?*https://github.com/w3c/csswg-drafts/issues/3720*
推薦閱讀??點擊標題可跳轉
[移動端體驗優化經驗總結與實踐](http://mp.weixin.qq.com/s?__biz=MzAxODE2MjM1MA==&mid=2651557392&idx=1&sn=8803d7052575f09e18d5076ee6ba49ae&chksm=802559d1b752d0c701825497ce2defb2135e7e4d70014d7f95cc155d4050d921419813ccf57f&scene=21#wechat_redirect)
[基于 Vue 和 TS 的 Web 移動端項目實戰心得](http://mp.weixin.qq.com/s?__biz=MzAxODE2MjM1MA==&mid=2651557116&idx=2&sn=12e617f37864556f974108fee6a25eb1&chksm=80255b3db752d22bdbac8e22a0abf46610bb7a15d5ff3a671fd9659038ba26e139146866863e&scene=21#wechat_redirect)
[關于移動端開發 1px 線的一些理解和解決辦法](http://mp.weixin.qq.com/s?__biz=MzAxODE2MjM1MA==&mid=2651556534&idx=1&sn=9e820e7b912550f9cfc1256ad3a477f2&chksm=80255d77b752d46149dbda1d8b44dea2ca2c88da00ed7c88b402ad929341b25a898b58853e65&scene=21#wechat_redirect)
覺得本文對你有幫助?請分享給更多人
關注「前端大全」加星標,提升前端技能

好文章,我在看??
[閱讀原文](https://mp.weixin.qq.com/s/ysPmhr0zwscxPE3Q_xtY3w##)
- 開始
- 微信小程序
- 獲取用戶信息
- 記錄
- HTML
- HTML5
- 文檔根節點
- 你真的了解script標簽嗎?
- 文檔結構
- 已經落后的技術
- form表單
- html實體
- CSS
- css優先級 & 設計模式
- 如何編寫高效的 CSS 選擇符
- 筆記
- 小計
- flex布局
- 細節體驗
- Flex
- Grid
- tailwindcss
- JavaScript
- javascript物語
- js函數定義
- js中的數組對象
- js的json解析
- js中數組的操作
- js事件冒泡
- js中的判斷
- js語句聲明會提前
- cookie操作
- 關于javascript你要知道的
- 關于innerHTML的試驗
- js引擎與GUI引擎是互斥的
- 如何安全的修改對象
- 當渲染引擎遇上強迫癥
- 不要使用連相等
- 修改數組-對象
- 算法-函數
- 事件探析
- 事件循環
- js事件循環中的上下文和作用域的經典問題
- Promise
- 最佳實踐
- 頁面遮罩加載效果
- 網站靜態文件之思考
- 圖片加載問題
- 路由及轉場解決方案
- web app
- 寫一個頁面路由轉場的管理工具
- 談編程
- 技術/思想的斗爭
- 前端技術選型分析
- 我想放點html模板代碼
- 開發自適應網頁
- 后臺前端項目的開發
- 網站PC版和移動版的模板方案
- 前后端分離
- 淘寶前后端分離
- 前后端分離的思考與實踐(一)
- 前后端分離的思考與實踐(二)
- 前后端分離的思考與實踐(三)
- 前后端分離的思考與實踐(四)
- 前后端分離的思考與實踐(五)
- 前后端分離的思考與實踐(六)
- 動畫
- 開發小技巧
- Axios
- 屏幕適配
- 理論基礎
- 思考
- flexible.js原理
- 實驗
- rem的坑,為什么要設置成百分比,為什么又是62.5%
- 為什么以一個標準適配的,其它寬度也能同等適配
- 自適應、響應式、彈性布局、屏幕適配
- 適配:都用百分比?
- 番外篇
- 給你看看0.5px長什么樣?
- 用事實證明viewport scale縮放不會改變rem元素的大小
- 為什么PC端頁面縮放不會影響rem元素
- 究竟以哪個為設備獨立像素
- PC到移動端初試
- 深入理解px
- 響應式之柵格系統
- 深入理解px(二)
- 一篇搞定移動端適配
- flex版柵格布局
- 其他
- 瀏覽器加載初探
- 警惕你的開發工具
- JS模塊化
- webpack
- 打包原理
- 異步加載
- gulp
- 命名規范
- 接口開發
- sea.js學習
- require.js學習
- react學習
- react筆記
- vue學習
- vue3
- 工具、技巧
- 臨時筆記
- 怎么維護好開源項目
- 待辦
- 對前端MVV*C框架的思考
- jquery問題
- 臨時
- 好文
- 節流防抖