淺談移動端 css 適配解決方案 (附 Vue-cli3 中使用)

說到移動端佈局,你們想到的是什麼解決方案呢,百分比?rem?仍是 vw/vh, 最近公司的項目牽扯到了,再加上本人以前移動端適配的作的比較少,因此在這裏重點記錄下這個項目的解決方案,大體參考 大漠老師 的團隊的思路。css

首先說問題

咱們的論點,說的並非該如何佈局,該去採用哪一種佈局方式,而是,有時候咱們會發現,當咱們在適某一機型的時候,顯示上沒什麼問題。可是一旦我換到另一部手機,發現出現了 模糊 的狀況,尤爲以圖片更爲顯著。html

基本概念

視口 viewport前端

視窗有三個部分:vue

  • 可視視口(Visual viewport)。 顧名思義,就是用戶能夠看到的窗口,經過滾動縮放去改變可視窗口的大小,visual viewport的寬度能夠經過window.innerWidth
  • 佈局視口(Layout viewport)。 這裏說 CSS,CSS佈局(尤爲是百分比寬度)是相對於佈局視口計算的,佈局視口比視覺視口寬得多,你能夠放大縮小或者滾動但是窗口,可是佈局窗口的元素大小和形狀是不變的。這個layout viewport的寬度能夠經過 document.documentElement.clientWidth 來獲取
  • 理想視口 (ideal viewport) 。關於不一樣的設備ideal viewport的寬度都不一樣,能夠到http://viewportsizes.com去查看一下,裏面收集了衆多設備的理想寬度。

ppk大神對於移動設備上的viewport有着很是多的研究(第一篇第二篇第三篇),有興趣的同窗能夠去看一下,本文中有不少數據和觀點也是出自那裏。ppk認爲,移動設備上有三個viewport。html5

物理像素 physical pixelwebpack

物理像素又叫設備像素,顯示屏是由一個個物理像素點組成的,在同一個設備上,它的物理像素是固定的,這是廠商在出廠時就設置好了的,即一個設備的分辨率是固定的。單位pt。git

設備獨立像素 Device Independent Pixelgithub

也叫 邏輯像素,表明能夠經過程序控制使用的虛擬像素,是一個整體概念,包括了CSS像素web

css 像素編程

適用於web編程,指的是咱們在樣式代碼中使用到的邏輯像素,是一個抽象概念,實際並不存在。

設備像素比 device pixel ratio

設備像素比簡稱爲dpr,其定義了物理像素和設備獨立像素的對應關係。它的值能夠按下面的公式計算獲得:

設備像素比(dpr) = 物理像素 / 設備獨立像素
複製代碼

在JavaScript中,能夠經過window.devicePixelRatio獲取到當前設備的dpr。

這裏舉個 🌰 ,在iphone 4中,物理像素是640*960(關於其餘iphone機型的物理像素可參考 這裏)他的 dpr 爲 2 ,因此他的 設備獨立像素(邏輯像素)爲 320x480 。

這裏就比較容易理解了。咱們以前說 邏輯像素 包括css像素,因此 css 在 iPhone4 中 1px 對應的 物理像素爲 2個物理像素
爲何在 pc 中不存在佈局的這些東西,其實也是存在的,咱們把相似 PC 這種屏幕 叫 普通屏 由於他實際上是 1px 爲 對應 1個物理像素。而這種 一個邏輯像素 不對應 一個物理像素 的 屏幕就叫作 Retina屏 能夠看這張圖:

普通屏

Retina 屏

再來兩個更直觀的:

因此咱們大概瞭解問題的答案了:

理論上來講,1個位圖像素對應1個物理像素,才能等到完美清晰的展現。

前端解決方案

rem + 縮放比例

rem 這個點就很少說了。 meta 標籤你們應該都會很熟悉

<meta name = "viewport" content ="width=device-width, initial-scale=1.0">
複製代碼

initial-scale 這個頗有意思是就是說縮放的比例。我忽然想叫他 黃金 1:1

原理其實也很簡單,這裏擺一張圖:

因此 2 倍屏幕 的 initial-scale 是 0.5 ,3倍屏幕的 initial-scale 是 0.3333 ,對應的 rem 放大相應的倍數,就能夠達到 黃金 1:1 的高清 狀態了。

著名的例子有: Flexible的佈局方案

vw 的橫空出世

爲了解決這類問題,原生的CSS,就能夠作到 這種 縮放比例的控制-----vw。
咱們來看爲何 :

vw是基於Viewport視窗的長度單位,這裏的視窗(Viewport)指的就是瀏覽器可視化的區域,而這個可視區域。以前的 rem 縮放 其實就是問了解決 ideal viewport 和 dpr 作的 hack, 所以有了 vw 咱們就能夠 幹掉 那些 dpr 判斷的縮放了。 好比設計稿的寬度爲 750px; 那麼 100vw = 750px,即1vw = 7.5px。那麼咱們能夠根據設計圖上的像素換算成 vm 佈局就能夠了。這時候你們會說怎麼會這麼麻煩。。。算了算了,等下別跑,咱們還有webpack ,咱們還有loader,還有 。。。postcss

VUE 中的實戰方案

這裏參考 大漠老師的 這篇文章 廢話很少說,先列插件:

以後再 項目中的 package.json 中添加 下列配置

"postcss": {
        "plugins": {
            "autoprefixer": {},
            "postcss-import": {},
            "postcss-url": {},
            "postcss-aspect-ratio-mini": {},
            "postcss-cssnext": {},
            "postcss-px-to-viewport": {
                "viewportWidth": "750", //視窗的寬度,對應的是咱們設計稿的寬度,通常是750
                "unitPrecision": "3",//指定`px`轉換爲視窗單位值的小數位數(不少時候沒法整除)
                "viewportUnit": "vw", //指定須要轉換成的視窗單位,建議使用vw
                "selectorBlackList": [ //指定不轉換爲視窗單位的類,能夠自定義,能夠無限添加,建議定義一至兩個通用的類名
                    ".ignore",
                    ".hairlines"
                ],
                "minPixelValue": 1, // 小於或等於`1px`不轉換爲視窗單位
                "mediaQuery": false// 容許在媒體查詢中轉換`px`
            },
            "cssnano": {
                "preset": "advanced",
                "autoprefixer": false,
                "postcss-zindex": false //只要啓用了這個插件,z-index的值就會重置爲1,必定關閉
            }
        }
    },
複製代碼

而後就能夠開心的寫代碼了。好比設計稿給定多少像素就寫多少。postcss 會自動幫你計算 應當轉換爲 多少 vw 。貼個圖吧

編譯後的:

結語

最後,其實還有一些問題,會有 1px 的經典問題,這裏埋個伏筆吧。你們有好的方案能夠提出來,我也是半路出家,因此有不一樣見解的歡迎討論。分享無罪,歡迎組隊。雙壓,哈哈哈碎覺

相關文章
相關標籤/搜索