移動端佈局適配

始終保持視覺稿比例的移動端佈局

佈局要求:

因爲手機的屏幕寬度大小不一,因而在佈局複雜的移動端頁面開發中咱們就存在這樣一個需求:css

自適應不一樣寬度的設備,最大程度還原視覺稿比例。html

演變過程 :

假如一個相似淘寶手機端首頁的頁面佈局須要你去實現,你須要適配不一樣尺寸的手機終端前端

解決方案1:百分比佈局
git

可能你首先想到的會是百分比佈局github

問題:百分比參照的容器的寬度是不一樣的,須要一個統一的參照,佈局比較複雜的狀況不太適用,這種方法也不利於後續佈局變動的維護。web

解決方案2:rem + 媒體查詢c#

也是我最先接觸移動端開發的時候使用的方法,使用rem單位。瀏覽器

html{
  font-size:50px;
}
.div1{
  width:.5rem;
}
.div2{
  width:1rem;
}複製代碼

以上只是實現了參照的統一,並無達到不一樣終端適配的效果,因而咱們加上了這樣子的一些媒體查詢。bash

...
@media screen and (min-width: 361px) and (max-width: 375px) {
  html {
    font-size: 50px;
  }
}
@media screen and (min-width: 376px) and (max-width: 393px) {
  html {
    font-size: 52.4px;
  }
}
@media screen and (min-width: 394px) and (max-width: 412px) {
  html {
    font-size: 54.93px;
  }
}
...

.div1{
  width:.5rem;
}

.div2{
  width:1rem;
}複製代碼

仍然,咱們的實現效果是 trace1 所示app

可是理想的狀況是 trace 0

解決方案3:手淘 2015 年出的方案 flexible.js

做者在2019年1月更新了這樣一段話,說明如今已經不推薦你們來採用這個方案了,並提供一篇文章說明如今推薦採用的新方案,這個咱們後續會講到。

這個方案的原理是經過 js 來動態計算根節點的 font-size,而後結合 rem 來實現。這裏附上 GitHub 倉庫的地址

除此以外,flexible.js 中另一個比較重要的想法是實現了頁面中物理像素和 css 像素的數量一致,它根據設備的 dpr (設備像素比)對 viewport 進行了縮放(固然僅限於安卓設備)。解決了 Retina 屏幕下1px border的問題,更準確的說是 dpr 爲 2 的設備中如何實現0.5px border的問題,由於設備能展現的最小單元是一個物理像素,因此dpr 爲 2 的設備能展示的最小單位是0.5px。有相關的文章說它也解決了 Retina 屏幕下圖片模糊的問題,物理像素值與css像素值相等,致使屏幕不會由於 css 像素值 < 物理像素值而從周圍的點取色值。

更詳細的對該方案的介紹和相關物理像素css像素dpr 的背景知識的介紹,能夠閱讀這兩篇文章:

理解flexible.js所需的viewport知識

關於移動端適配,你必需要知道的

值得注意的是,因爲縮放了viewport,會致使咱們在 css 中若是使用 px 單位,在不一樣 dpr 設備中所展示的效果是不同的,須要根據 dpr 值作一些額外的處理。例如:

@mixin font-dpr($font-size){
    font-size: $font-size;​
    [data-dpr="2"] & {
        font-size: $font-size * 2;
    }
​    [data-dpr="3"] & {
        font-size: $font-size * 3;
    }
}
@include font-dpr(16px);複製代碼

若是你想要使用媒體查詢,在這個方案中也是不太友好的。

解決方案4:視口單位的使用

在 CSS 規範中,有4種類型的可用視口單位:

  • vw --- 1vw 等於視口寬度的 1%

  • vh --- 1vh 等於視口高度的 1%

  • vmin --- vw 和 vh 中的較小值

  • vmax --- vw 和 vh 中的較大值

視口,即瀏覽器屏幕大小,1vw 等於瀏覽器寬度的 1%,100vw 即整個瀏覽器的寬度。


目前瀏覽器對視口單位的兼容性覆蓋率已經90% +,咱們可使用 vw 來實現適配。 viewport 單位的瀏覽器兼容性

其他3個單位經常使用的場景以下:

vh : vh 比較經常使用的狀況是100 vh , 使得高度撐滿整個屏幕。

vmin,vmax: 解決移動端中橫屏顯示的問題

應用場景1: 實現固頂的導航欄

應用場景2: 固定寬度或高度的div


使用 vw 推薦採用的解決方案

1.網易新聞的解決辦法

地址:3g.163.com/touch/news/

首先咱們須要將咱們的視口變爲理想視口

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

PC 端中默認視口的寬度就等於設備的寬度,可是在移動端的瀏覽器中不是。爲了讓未適配手機視圖的PC端網頁在移動端中也能比較完整的展現,手機端的瀏覽器作了相應的處理,默認的 viewport 寬度會大於真實設備的寬度(在 IOS 中默認的 html 的寬度是 980px)。

width=device-width 的做用其實就是讓咱們在css 代碼裏面寫的 px 對應真實設備上的 px 值。

如今咱們的視口寬度就等於設備的寬度了,在設備寬度爲375 px 的 IPhone6 中

html{  width: 13.33333333vw}複製代碼

就等同於設置了 font-size: 50px。網易新聞採用的方案以下:

結合了媒體查詢來處理 vw 的兼容性問題,若是不支持 vw 單位,能夠降級爲使用固定的 px。

···
@media screen and (min-width: 361px) and (max-width: 375px) {
  html {
    font-size: 50px;
    font-size: -webkit-calc(13.33333333vw);
    font-size: calc(13.33333333vw);
  }
}
@media screen and (min-width: 376px) and (max-width: 393px) {
  html {
    font-size: 52.4px;
    font-size: -webkit-calc(13.33333333vw);
    font-size: calc(13.33333333vw);
  }
}
@media screen and (min-width: 394px) and (max-width: 412px) {
  html {
    font-size: 54.93px;
    font-size: -webkit-calc(13.33333333vw);
    font-size: calc(13.33333333vw);
  }
}
···複製代碼

而後在實際的佈局中使用 rem

可使用 vscode 插件 px2rem 來進行轉化,也可全局轉化。


2.flexible.js 做者新提出的解決方案

不推薦使用flexible.js以後,做者大漠在如何在Vue項目中使用vw實現移動端適配中有提到使用 Postcss 插件結合 vw 解決方案。做者在文章最末尾給出了實現的 demo 與下載的連接。

"dependencies": {
    "cssnano": "^3.10.0",  // 壓縮與優化css
    "postcss-aspect-ratio-mini": "0.0.2", // 處理元素容器寬高比
    "postcss-cssnext": "^3.1.0",  // css的polyfill
    "postcss-px-to-viewport": "0.0.3", // 編譯時將px轉化爲視口單位
    "postcss-viewport-units": "^0.1.3", // 處理視口單位的兼容性問題
    "postcss-write-svg": "^3.0.1" // 用來解決1px的border的問題
}複製代碼

cssnanopostcss-cssnext 的補充知識瞭解。

cssnano: github.com/iuap-design…

postcss-cssnextgithub.com/jiayisheji/…

而後在.postcssrc.js文件對新安裝的PostCSS插件進行配置。

module.exports = {
    "plugins": {
        "postcss-import": {},
        "postcss-url": {},
        "postcss-aspect-ratio-mini": {},
        "postcss-write-svg": {
            utf8: false
        },
        "postcss-cssnext": {},
        "postcss-px-to-viewport": {
            viewportWidth: 750,     // (Number) The width of the viewport. 
            viewportHeight: 1334,    // (Number) The height of the viewport.
            unitPrecision: 3,       // (Number) The decimal numbers to allow the REM units to grow to.
            viewportUnit: 'vw',     // (String) Expected units.
            selectorBlackList: ['.ignore', '.hairlines'],  // (Array) The selectors to ignore and leave as px.
            minPixelValue: 1,       // (Number) Set the minimum pixel value to replace.
            mediaQuery: false       // (Boolean) Allow px to be converted in media queries.
        },
        "postcss-viewport-units":{},
        "cssnano": {
            preset: "advanced",
            autoprefixer: false,
            "postcss-zindex": false 
       }
    }
}複製代碼

文中還說起了對視口單位兼容性問題的解決方案:

採用 postcss-viewport-unitsviewport-units-buggyfill 結合的方法

postcss-viewport-units 在編譯時給視口單位增長 content 屬性,例如:

而後viewport-units-buggyfill經過這個content屬性來作兼容性處理。

最後附上做者 demo 的 Github地址


多種終端適配的方案

前面討論的都是純移動端中的問題,接下來咱們把討論的範圍擴大一下,若是咱們須要實現一個多終端適配的網站,應該要如何實現?

我選擇了一些比較典型的網頁,在瀏覽器中將窗口大小縮放,觀察效果。

方案1:出現橫向滾動條, 忽略IPad視圖

最小的PC端屏幕寬度是1280px,許多網站會將主體內容的寬度定在1200px,設置一個min-width:1200px,當窗口大小小於這個置時,出現橫向的滾動條。

示例網站1

百度FEX

小於 1200px 時,橫向出現滾動條,在 IPAD 下是出現橫向滾動條的,小於 640px 時,變到了手機端的視圖。

示例網站2

海康威視AI開放平臺,和示例網站1很類似,手機視圖變化的斷點定在了 768px。

方案2:全適配

示例網站1

騰訊ISUX

頁面內容比較簡單,佈局多采用塊狀,能比較方便的採用百分比, flex 或者是 grid 佈局結合媒體查詢來實現全適配。

示例網站2

css-tricks.com/

相比起網站1,頁面內容就比較複雜了,須要作多個媒體查詢的處理來實現效果。

網站的全局適配有不少種解決方法,不一樣視圖變化的斷點也不是固定的,你能夠根據你網站的內容來本身定義如何來變化。

固然,這些單憑前端來完成是不足夠的,設計師在出視覺稿的時候也須要考慮網頁在PC端,移動端,IPAD尺寸下視圖應當如何展示,並定義好各個視圖轉變的斷點值是多少,這樣才能保證咱們的頁面在不一樣屏幕尺寸下有良好的展示。


字體大小的適配

若是你選取了採用方案1,那某種程度上是能夠避免掉字體大小適配的問題的,只須要保持在PC端一個字體規範,移動端一個字體規範,界面最終的顯示並不會有問題。

若是採用了方案2,那你可能還須要考慮字體大小須要隨着屏幕大小而變化的問題。具體內容可參考掘金翻譯計劃中的這篇文章:Web 流式文字排版的現狀

文章大體的內容是做者發現,

視口單位被引入更可能是做爲絕對單位網頁佈局的一種擴展

1.拋出了一個問題:爲何不多有網站把它應用到字體大小當中?

2.總結出了一個 rem 和 vw 結合來控制字體大小的最佳實踐。( 帶 CSS 鎖的流式文字排版 )。

做者推導出這個公式

body {
  font-size: calc([minimum size] + ([maximum size] - [minimum size]) * ((100vw - [minimum viewport width]) / ([maximum viewport width] - [minimum viewport width])));
}複製代碼

咱們用一個張鑫旭的博客中提到的實際的例子來幫助理解一下

假設咱們但願瀏覽器寬度在 600px ~ 1000px 變化的時候,根元素的 font-size 大小是18px~22px之間對應變化的,默認根結點的字體大小是16px,那咱們能夠這樣子作

html { font-size: calc(112.5% + 4 * (100vw - 600px) / 400); }複製代碼

3.最後做者又回過頭來推翻了本身的論點,考慮到使用vw來實現字體的大小變化會引發無障礙訪問功能的問題,因此他並不提倡在實際的網站中採用這種作法。

好比使用 vw 來實現 div 的寬度,那麼在網頁縮放的時候所佔當前頁面的比例仍是一致的,同理若是用 vw 來實現font-size,縮放頁面大小也是不會改變的,對於一些須要使用無障礙功能將頁面字體放大來方便查看的人來講,這個顯示是不太合適的。


總結

將來視口單位的兼容性確定會愈來愈好,在移動端的適配中,對於元素的佈局能夠直接採用 vw,使用Postcss插件來讓咱們的開發更加方便與自動化。

多終端的適配有多種不一樣的解決方案,須要根據你當前網頁所要展示的內容肯定最適合本身的解決方案,固然須要與視覺實現溝通設計好不一樣屏幕尺寸下的展現效果。

對於字體的適配,在有須要的狀況下若是不考慮無障礙訪問功能的話,可使用這個帶 CSS 鎖的字體大小適配方案配合 rem 單位一塊兒使用。若是要考慮無障礙訪問功能,那就優雅的降級採用 media query + rem 來實現。


參考文章

基於視口單位的網頁排版

淺說移動前端中 Viewport 和 Viewport units

使用Flexible實現手淘H5頁面的終端適配

lib-flexible倉庫地址

理解flexible.js所需的viewport知識

關於移動端適配,你必需要知道的

基於vw等viewport視區單位配合rem響應式排版和佈局

如何在Vue項目中使用vw實現移動端適配

Web 流式文字排版的現狀

相關文章
相關標籤/搜索