響應式佈局的實現依靠媒體查詢( Media Queries )來實現,選取主流設備寬度尺寸做爲斷點針對性寫額外的樣式進行適配,但這樣作會比較麻煩,只能在選取的幾個主流設備尺寸下呈現完美適配。
即便是經過 rem 單位來實現適配,也是須要內嵌一段腳本去動態計算根元素大小。css

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

認識視口單位( Viewport units )

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

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

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

 

viewport.png

視口單位中的「視口」

 

根據CSS3規範,視口單位主要包括如下4個:瀏覽器

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

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

 

viewport.png

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

 

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

兼容性

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

 

caniuse_viewport.png

截圖來自Can I Use

 

 

wechat.jpg

截圖來自X5內核-Can I Use

 

利用視口單位適配頁面

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

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

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

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

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

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

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

1.對於設計稿的尺寸轉換爲vw單位,咱們使用Sass函數編譯

1
2
3
4
5
//iPhone 6尺寸做爲設計稿基準
$vw_base: 375;
@function vw( $px) {
@return ( $px / 375) * 100vw;
}

2.不管是文本仍是佈局高寬、間距等都使用 vw 做爲 CSS 單位

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
.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: vw(2);
}
}
}
}

3.1物理像素線(也就是普通屏幕下 1px ,高清屏幕下 0.5px 的狀況)採用 transform 屬性 scale 實現。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
.mod_grid {
position: relative;
&::after {
// 實現1物理像素的下邊框線
content: '';
position: absolute;
z-index: 1;
pointer-events: none;
background-color: #ddd;
height: 1px;
left: 0;
right: 0;
top: 0;
@ media only screen and (-webkit-min-device-pixel-ratio: 2) {
-webkit- transform: scaleY(0.5);
-webkit- transform-origin: 50% 0%;
}
}
...
}

4.對於須要保持高寬比的圖,應改用 padding-top 實現

1
2
3
4
5
6
7
8
9
10
11
12
13
.mod_banner {
position: relative;
padding-top: percentage(100/750); // 使用padding-top
height: 0;
overflow: hidden;
img {
width: 100%;
height: auto;
position: absolute;
left: 0;
top: 0;
}
}

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

 

layout.png

體驗地址點擊此處

 

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

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

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

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

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// rem 單位換算:定爲 75px 只是方便運算,750px-75px、640-64px、1080px-108px,如此類推
$vw_fontsize: 75; // iPhone 6尺寸的根元素大小基準值
@function rem( $px) {
@return ( $px / $vw_fontsize ) * 1rem;
}
 
// 根元素大小使用 vw 單位
$vw_design: 750;
html {
font-size: ($vw_fontsize / ($vw_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單位使用祕笈來交流交流~:)

參考文檔

感謝您的閱讀,本文由  凹凸實驗室 版權全部。如若轉載,請註明出處:凹凸實驗室( https://aotu.io/notes/2017/04/28/2017-4-28-CSS-viewport-units/