通常來說PC端的頁面並不像移動端頁面那樣對屏幕大小和分別率有那么強的依賴。一般的頁面都是取屏幕中間的一塊寬度(1280px), 兩邊留白, 高度隨着內容的長度滾動。這樣無論窗口怎么變化,頁面都是可用的。比如,我們的這個頁面. 然而也有少數的頁面,天生就是要在 pc 端全屏顯示的,其中最為典型的代表就是全屏的 dashboard 頁面。比如:
當然,如果 dashboard 頁面是內嵌在一些管理頁面里的,通常是允許滾動的。
但是,如果 dashboard 是用於官方宣傳,比如在電視機或者廣告屏上的展示的時候,通常是不允許滾動條出現的。比如:
這種 dashboard 有個帥氣的名字叫數據可視化。
通常的做法
為了實現全屏的這種 dashboard, 通常的做法就是要對寬度和高度都做百分比(網格)來實現了。但是這種方案的缺點在於:
- 實現太麻煩。設計師給的設計稿通常是 px 為單位標注的,我們需要仔細的計算寬度和高度的比例,然后小心處理頁面的布局。
- 難以處理屏幕寬高比與設計圖不符時,帶來的元素變形。所以最后展示的屏幕不能和設計稿的屏幕的寬高比差距太大。
比如,下面這個簡單的頁面就是用百分比方案來做的。設計師給的圖的比例為 16: 9。
當窗口比例是 16 : 9 的時候黃色的長方形顯示符合設計,當窗口變成正方形的時候,黃色部分也跟着變方了,這必然會影響顯示效果。
可以在瀏覽器中打開,改變窗口大小頁面來體驗這個百分比方案。
理想的效果
我心目中的理想效果可能是像下面這個頁面一樣,無論窗口怎么變,我們的內容都保持原來的比例,並盡量占滿窗口(類似 background contain 的效果)。
- 屏幕尺寸和設計稿比例(16:9)一致時,占滿屏幕
- 屏幕尺寸比設計圖比例瘦時,上下留白,左右占滿,並上下居中, 顯示的比例保持16:9
- 屏幕尺寸比設計圖比例胖時,左右留白,上下占滿,並左右居中, 顯示的比例保持16:9
可以在瀏覽器中打開,改變窗口大小頁面來體驗這個flexible方案
rem 方案
熟悉移動端的自適應方案的朋友對 rem 適應方案,肯定不陌生,最出名的就是阿里的 lib-flexible 方案。可能你已經猜到,本文的這個方案肯定也是基於 rem 的.
rem (font size of the root element), 是 css3 的引入的一個大小單位。即相對於根元素的 font-size 值的大小。所謂根元素在網頁里一般就是 html. 舉例說明:下例中,html 的 font-size 大小
是 20px, 那么 1.4rem 和 2.4 rem 就分別代表着 28px 和 48px 了。
假設我們的設計稿其尺寸為 1920 * 1280 px,並且實際運行這個網頁的屏幕分別率也是 1920 * 1280. 那么,這網頁就好做了。簡單粗暴地,按圖中的元素的尺寸和位置,直接利用絕對定位把所有元素擼出來就行了。比如,設計稿中有這樣一個元素:
這不剛介紹了 rem, 我們試着用 rem 為單位來寫一下 doughnut
元素的 css。我們把頁面的 html 元素的 font-size 設置為 1920 / 10 = 192 px. 那么 doughnut
這個元素就應該寫作:
恩。。。。這不是有病么?算成 rem,然后設置一下 html 的 font-size 讓瀏覽器再算回去?顯擺自己的數學好么?23333。
注意上上面有一個假設,屏幕大小正好是 1920 * 1280。這個假設真的很假,根本不可能,一旦用了 px,那么一切長寬都死了。這時你再看一眼 rem,真實的長度為:
那么這個實際長度必然有一下特點:
- 所有長度的比例必然和設計圖一致。
- 實際的顯示長度完全由
html 的 font-size
值決定(線性關系)。
我們來證明一下:
設:設計稿上有任一1條線: A, A 的長度為 xx,
計算 rem 值的基准
為 zz
那么 css 里,A 的長度表示為 xzxz (rem)設網頁運行時的 html 的 font-size 值為 fsfs,
那么 A 的實際顯示長度就分為 xfszxfsz (px)
所以:
- 對於任意2條線,其實際長度的比例為 x1fszx1fsz : x2fszx2fsz 就等於 他們在設計圖上的比例 x1x1 : x2x2
- 對於任意一條線,xx 和 zz 是固定值,其實際值隨着 fsfs 值線性關系變化的
我們取設計圖的邊框的4條線來分析, 那么設計稿
,真實顯示(畫布)
和 顯示窗口(全屏時,即為屏幕)
的關系如下圖所示:
- 設計稿的寬高分別為 axax 和 ayay, 比例為 xx : yy.
- 實際顯示的范圍(我們稱其為畫布)比例和設計稿保持一致,所以可以設實際顯示的畫布的寬高為bx:bybx:by, 且所有線的實際顯示長度是由
html 的 font-size 值
fsfs 線性決定的。 - 屏幕的尺寸不確定,假設其寬度為 ww, 高度為 hh
小結一下,用了上面提到的 rem 來方案后,我們做出來的頁面是一個和設計稿比例一致的,並且大小根據網頁運行時的 html 的 font-size的值縮放的頁面。
既然頁面的大小可以按html 的 font-size的值縮放,那么如果我希望畫布的實際顯示寬度始終和瀏覽器窗口寬度保持一致的話(即下圖這樣的狀態),html 的 font-size的值應該如何設置呢?
我們假設 計算 rem 值的基准
為設計稿寬度的 1q1q:
假設,設計稿窗口寬為 axax,高為 ayay, 則
計算 rem 值的基准
zz 為 axqaxq那么按上面的公式,瀏覽器中畫布實際的
寬度為 axfsaxq=fsqaxfsaxq=fsq,
高度為 ayfsaxq=qyfsxayfsaxq=qyfsx瀏覽器窗口的寬度 ww 要等於畫布實際的寬度,即 w=fsqw=fsq,則 fs=wqfs=wq
好的,從數學回到我們的工程中來,我們的設計稿尺寸是 1920 * 1280。我們取 qq 這個值為 10, 則 計算 rem 值的基准
zz 為 axq=192010=192axq=192010=192. 然后我們把所有元素的長、寬、位置、字體大小等原來 px
單位都轉換成 rem,網頁加載后,我們用 js 去計算當前瀏覽器窗口的寬度,並設置 html 的 font-size
fsfs 為當前瀏覽器窗口的寬度
ww 的 1q1q,即 w10w10,這樣我們就做出了一個100%寬度的、等比例縮放設計稿的頁面了。
通過這樣的設置,我就得到了一個和設計稿比例一致的,寬度與窗口大小一致的頁面。
到此為止,就是現有 rem 方案的核心內容了。
說了半天,都是別人的方案,讀者可能會問了,那博主你干了啥?
我的方案
回頭想一下,我們要的是什么?現在這個方案,能滿足我們的要求么?我們來逐條分析:
-
屏幕(窗口)尺寸和設計稿比例(x:yx:y)一致時,占滿屏幕
這種情況肯定沒問題,屏幕和真實頁面完美重合.
-
屏幕(窗口)尺寸比設計圖比例瘦時,上下留白,左右占滿,並上下居中, 顯示的比例保持(x:yx:y)
這種情況也沒問題,真實頁面高度小於屏幕,然后頁面內容上下居中就可以了。
-
屏幕(窗口)尺寸比設計圖比例胖時,左右留白,上下占滿,並左右居中, 顯示的比例保持(x:yx:y)
問題出現了,在這種場景下,頁面的高度超出了屏幕的高度,這就會導致垂直滾動條了。這就是我的方案處理的地方了。在這種場景下,我們需要頁面的高度縮小為屏幕的高度,當然為了保持比例頁面的寬度等也要等比例縮小.換句話說我們要把所有的線的長度等比例縮小,縮小后畫布的高度要等於屏幕的高度,即下圖所示的狀態:
要等比例縮小所有的長度,那么操作 html 的 font-size
fsfs 的值就能做到了。我們上面的分析中,我們已經計算了頁面(畫布)的真實高度
那么按上面的公式,瀏覽器中頁面(畫布)的真實
高度為 ayfsaxq=qyfsxayfsaxq=qyfsx
在此場景下,我們需要把畫布真實高度值縮小到屏幕的高度,
設窗口的高度為 hh,
設縮小比例為 ss, 則有 h=qyfsxsh=qyfsxs, 得 s=xhqyfss=xhqyfs
即我們需要在頁面(畫布)真實高度上 qyfsxqyfsx 乘上個縮小系數 xhqyfsxhqyfs,可以使頁面(畫布)的真是高等於窗口的高度了
又因為 fs=wqfs=wq, 則這個縮小系數可變換為:
xhqywq=xhyw=xy/whxhqywq=xhyw=xy/wh, 即