純CSS使用vw和vh視口單位實現自適應

編者注:在移動端中利用rem的相對於根HTML進行改變,經過一段時間JS實現了移動端自適應,本文則使用純CSS視口單位來自行自適應,雖然如今的兼容性還無法徹底可以接受,但不妨礙你認識這個vw和vh的強大。css

響應式佈局的實現依靠媒體查詢(Media Queries)來實現,選取主流設備寬度尺寸做爲斷點針對性寫額外的樣式進行適配,但這樣作會比較麻煩,只能在選取的幾個主流設備尺寸下呈現完美適配。html

即便是經過rem單位來實現適配,也是須要內嵌一段腳本去動態計算根元素大小。ios

近年來,隨着移動端對視口單位的支持愈來愈成熟、普遍,使得咱們能夠嘗試一種新的辦法去真正地適配全部設備尺寸。瀏覽器

認識視圖單位(Viewport units)

首先,咱們要了解什麼是視口。微信

在業界,極爲推崇的一種理論是Peter-Paul Koch(江湖人稱"PPK大神")提出的關於視口的解釋---在桌面端,視口指的是在桌面端瀏覽器的可視區域;而在移動端較爲複雜,它涉及到三個視口,分別是:Layout Viewport(佈局視口)Visual Viewport(視覺視口)Ideal Viewport函數

而視口單位中的 "視口",在桌面端,毫無疑問指的就是瀏覽器的可視區域;可是在移動端,它指的則是三個Viewport中的Layout Viewport佈局

根據css規範,視口單位主要包括如下4個:字體

  • vw:1vw等於視口寬度的1%
  • vh:1vh等於視口高度的1%
  • vmin:選取vw和vh中最小的那個
  • vmax:選取vw和vh中最大的那個

視口單位區別於%單位,視口單位是依賴於視口的尺寸,根據視口尺寸的百分比來定義的;而%單位則是依賴於元素的祖先元素。flex

用視口單位度量,視口寬度爲100vw,高度爲100vh(左側爲豎屏狀況,右側爲橫屏狀況)優化

例如,在桌面端瀏覽器視口尺寸爲650px,那麼1vw = 650 * 1% = 6.5px(這是理論推算得出,若是瀏覽器不支持0.5px,那麼實際渲染結果多是7px)。

兼容性

其兼容性以下圖有所示,能夠知道:在移動端ios8以上以及Android 4.4以上得到支持,而且在微信 x5 內核中也獲得完美的全面支持

截圖來自 Can I Use

利用視口單位適配頁面

對於移動端開發來講,最爲重要的一點是如何適配頁面,實現多終端的兼容,在不一樣的適配方式各有千秋,也各有缺點。

就主流的響應式佈局、彈性佈局來講,經過Media Queries 實現的佈局須要配置多個響應斷點,並且帶來的體驗也對用戶十分不友好:佈局在響應斷點範圍內的分辨率下維持不變,而在響應斷點切換的瞬間,佈局帶來斷層式的變化,如同卡帶的唱機般「咔咔咔」地一下又一下。

而經過採用rem單位的動態計算的彈性佈局,則是須要在頭部內嵌一段腳原本進行監聽分辨率的變化來動態改變根元素字體大小,使得CSS與js耦合在了一塊兒。

有沒有辦法可以解決這樣的問題呢?

答案是確定的,經過利用視口單位實現適配的頁面,是技能解決響應式斷層問題,又能解決腳本以來的問題的。

作法一: 僅使用vw做爲css單位

在僅使用vw做爲單位做爲惟一一種CSS單位的作法下,咱們遵照:

  1. 對於設計稿的尺寸轉換成vw單位,咱們使用Sass函數編譯
// iPhone 6 尺寸做爲設計稿基準
$vw_base: 375px;
@function vw($px) {
    @return ($px / $vw_base) * 100vw;
}
複製代碼
  1. 不管是文本仍是佈局寬度、間距等都使用vw做爲CSS單位
.mod_nav {
    background-color: #fff;
    &_list {
        display: flex;
        padding: vw(15) vw(10) vw(10); // 內間距
        &_item {
            flex: 1;
            text-align: center;
            font-size: vw(10); // 字體大小
            &_logo {
                display: block;
                margin: 0 auto;
                width: vw(40); // 寬度
                height: vw(40); //高度
                img {
                    display: block;
                    margin: 0 auto;
                    max-width: 100%;
                }
            }
            &_name {
                margin-top: vm(2);
            }
        }
    }
}
複製代碼
  1. 1px物理像素線(也就是普通屏幕下1px,高清屏幕下0.5px的狀況)採用transform 屬性 scale 實現。
.mod_grid {
    position: relative;
    &::after {
        // 實現1px的下邊框線
        content: '';
        position: absolute;
        z-index: 1;
        pointer-events: none;
        background-color: #ddd;
        height: 1px;
        left: 0;
        right: 0;
        top: 0;
        @media only screen and ()
    }
}
複製代碼
  1. 對於須要保持高寬比的圖,應改用padding-top實現
.mod_banner {
    position: relative;
    padding-top: percentage(100/700); // 使用padding-top
    height: 0;
    overflow: hidden;
    img {
        width: 100%;
        height: auto;
        position: absolute;
        left: 0;
        top: 0;
    }
}
複製代碼

由此,咱們可以實現一個常見佈局的頁面效果以下:

體驗地址點擊此處

作法二:搭配vw和rem,佈局更優化

這樣的頁面雖然看起來適配得很好,可是你會發現因爲它是利用視口單位實現佈局,依賴於視口大小而自動縮放,不管視口過大仍是太小,他也隨着視口過大或者太小,失去了最大最小寬度的限制。

固然,你能夠不在意這樣微小的不友好用戶體驗,但咱們仍是嘗試下追求修復這樣的小瑕疵吧。

因而,聯想到不如結合rem單位來實現佈局?rem彈性佈局的核心在於動態改變根元素大小,那麼咱們能夠經過:

  1. 給根元素大小設置隨着視口變化而變化的vw單位,這樣就能夠實現動態改變其大小。
  2. 限制根元素字體大小的最大最小值,配合body加上最大寬度和最小寬度

這樣咱們就可以實現對佈局寬度的最大最小限制。所以,根據以上條件,咱們能夠得出代碼實現以下:

// rem 單位換算: 定位75px 只是方便運算, 750-75px、 640-64px、 1080-108px, 如此類推
$vw_fontsize: 75; // iPhone6 尺寸的根元素大於基準值
@function rem($px) {
    @return ($px / $vm_fontsize) * 1rem;
}
// 根元素大小使用vw單位
html {
    font-size: ($vm_fontsize / ($vm_design / 2)) * 100vw;
    // 同時,經過Media Queries 限制根元素最大值,最小值
    @media screen and (max-width: 320px) {
        font-size: 64px;
    }
    @media screen and (min-width:540px) {
        font-size: 108px;
    }
}

// body 也增長最大最小寬度限制,避免默認100%寬度的block元素跟隨body而過大太小
body {
    max-width: 540px;
    min-width: 320px;
}
複製代碼

這裏就再也不給出截圖,但能夠點擊此處在線地址進行體驗。

小結

相對於作法一,我的比較推崇作法二,有如下兩點緣由:

第一,作法二相對來講用戶視覺體驗更好,增長了最大最小寬度的限制;

第二,更重要是,若是選擇主流的rem彈性佈局方式做爲項目開發的適配頁面方法,那麼作法二更適合於後期項目從rem單位過渡到vw單位。只須要經過改變根元素大小的計算方式,你就能夠不須要其餘任何的處理,就無縫過渡到另外一種CSS單位,更況且vw單位的使用必然會成爲一種更好的適配方式,目前它只是礙於兼容性的支持而得不到普遍的應用。

後語

這是筆者在偶然中閱讀到[翻譯]使用VH和VW實現真正的流體排版這一篇文章獲得的感悟與成果,也滿心歡喜地期待這篇文章一樣可以帶給讀者一些啓發,並提出一些vw單位的使用祕笈來就留交流~:)

此文爲轉載。原文: 凹凸實驗室 aotu.io/notes/2017/…

相關文章
相關標籤/搜索