rem, vw, 還是...? 各憑本事的移動端適配方案

pandaGao發表於2018-10-14

前言

2018年最後的法定假期都已經結束了,我相信大部分正在進行或曾經進行過移動端頁面開發的同學都或多或少的瞭解過使用rem進行移動端頁面適配的方案以及使用vw的方案,(沒了解過的同學可以參見大漠老師的這兩篇文章 使用Flexible實現手淘H5頁面的終端適配再聊移動端頁面的適配)也面臨過在不同適配方案間進行抉擇的思考,我個人最近對於移動端適配方案也進行了一輪重新的研究,期間,對各種適配方案也有一些自己的見解,正好記錄下來與大家一起分享。

vw與rem方案中的一些思考

所以,移動端適配 = vw or rem ?

當然不是。並不是所有場景下的移動端頁面都適合採用vw或rem的方案,這類方案的本質是佈局等比例的縮放,讓頁面在不同尺寸的螢幕下有類似於向量圖片縮放的效果,即保證頁面各元素之間位置尺寸的比例關係,並讓元素可以清晰地展現。 這樣的方案更適合於視覺元件種類較多,視覺設計對元素位置的相對關係依賴較強的移動端頁面。其實大部分頁面都可以使用rem或vw的方案進行適配,但對於文字內容較多,或者說希望引導使用者沉浸瀏覽的頁面,我個人並不推薦使用等比縮放的方案,至少並不推薦完全使用等比縮放的方案,對於文字內容還是應該直接使用px這種絕對長度單位,畢竟在大屏手機上使用者希望看到的是更多的內容而不是更大的內容。實際上很多這類的網站也確實是直接使用px結合flex等佈局方式進行移動端適配的,這個在後面討論具體技術方案的時候我會舉幾個例子。

rem方案到底在做什麼?

在各種rem適配方案的實現中,有兩個核心的點

  • 設定<meta name="viewport" content="xxx">(可以根據dpr縮放viewport,也可以直接使用1倍的視口大小)
  • 根據當前佈局的寬度(通常是viewport寬度, 也可以是被限制的最大/最小布局寬度)來設定html元素的font-size

之前我已經提到過,vw和rem的方案的本質都是“等比例縮放”,因為vw和rem都是相對長度單位(relative length unit),可以很好的滿足這個需求。區別是vw是viewport width的1%,而rem是html元素的font-size。當我們讓html元素的font-size與viewport width產生了關聯後,rem就可以模擬出使用vw進行佈局的效果了。所以在rem方案中,我們只是在把rem當做是vw的影子。寫作rem,讀作vw...(劇情似乎狗血起來了... rem: 當然是選擇原諒你們啊)

我rem有話說

那直接用vw不就完事兒了嗎?

且慢
且慢,當初之所以使用rem的方案流行開來正是因為在那時viewport units的瀏覽器支援程度不甚理想(IOS 8+, Android 4.4+ 參見viewport units的caniuse)。而相比較之下rem就好多了(IOS 4.1+, Android 2.1+ 參見caniuse),所以對於vw,在當時的大環境下前端想說愛你不容易。

我想這時候有人要說了:“醒醒兄弟 已經8102年了!” 是的,8102年都快要過去了,對於相容性要求不是特別高的情況下vw也算是可以見天日了,並且也有一些針對vw的補丁方案,但還有一個問題我們要稍微討論一下...

vw可以完全替代rem嗎?

回答依舊是否定的。單純使用vw進行佈局不能限制佈局的寬度,對於有這個需求的場景至少還是需要將vw和rem混用來處理邊界情況。下文也會更詳細地提到這種方案,這裡先按下不表。

現有生產環境中移動端適配方案的一點總結

當我們在苦苦地尋找適合自己的道路時,不妨先抬頭看看別人是怎麼做的。那麼現實世界裡各家網際網路公司的移動端頁面都採用了什麼樣的適配方案呢?有沒有一些比較有特色的絕活兒呢?以下我按照頁面實際使用的css長度單位作為劃分標準,為大家舉一些栗子。

px方案

就像開篇提到的,並不是說移動端就一定要使用相對長度單位,傳統的響應式佈局依然是很好的選擇,尤其在新聞,社群等可閱讀內容較多的場景直接使用px單位可以營造更好地體驗。px方案可以讓大螢幕手機展示出更多的內容,更符合人們的閱讀習慣。採用這種方案的網站有:

  • 騰訊

    移動端首頁主要是新聞內容,需要更好的閱讀體驗,適合直接使用px進行佈局。

  • 知乎

    知乎也是比較典型的追求閱讀體驗的場景,不出意外的也是直接使用px。

  • 點評

    視覺元素較豐富,依舊採用了px方案,頁面基本是flex佈局,適配效果很好

  • 頭條

    頭條的這個方案有點特色,依然會設定html元素的font-size也會加上data-dpr屬性並且會對viewport進行scale, 但是最終css的輸出還是px,並沒有使用rem,並且會對不同dpr下的樣式單獨定義,如下圖所示:

    頭條的適配方案
    這樣可以解決1px border的問題,文字大小也不會隨螢幕尺寸變動(畢竟文字內容較多),雖然我暫時沒找到使用到rem的地方,但確實可以在需要的時候對特殊元素做rem方案的佈局,不過這種方案應該會造成css檔案大小倍增,而且輸出這樣的css肯定也少不了構建流程外掛的支援,算是一種特定的解決方案吧。

看到這裡你以為最終輸出px就不能做類似於rem/vw的彈性佈局了嗎,下面就給大家看一手絕活兒...

  • 淘寶

    什麼?給我們看了半天文章結果用的是px?

    喵喵喵
    其實聰明的你一定很快就會發現在效果上淘寶移動端的適配方案和rem/vw的方案其實是差不多的,元素的樣式都是通過js生成的,雖然單位確實是px,但是方案依舊是以375px寬度的尺寸為基準進行縮放的。原理上應該是一種css in js的方案,只不過把rem方案中設定html元素font-size的過程內化到使用js計算元素style的過程中去了。這樣的方案涉及到整體的開發框架上的統一與支援,並不算是一個特別通用的方案。好處可能是直接使用px單位結果更為精確。可以說是一手絕活兒了。當然淘寶旗下還是有非常多的產品線的,也未必是同樣的適配方案(比如大漠老師文中的例子),這裡只針對這個移動端首頁來說。

rem方案

rem方案可以說是比較成熟了,出鏡率也較高,也就不再贅述了,總的來說rem方案主要分為兩種,一種是縮放viewport的方案,如當年的lib-flexible,可以對1px border等細節問題較方便的處理,但會影響到media query。另一種就是不縮放viewport,對1px boder等問題單獨引入處理方案。然後對於基準尺寸下的html元素fong-size也有很多不同的定義方式,這個說起來沒什麼標準可言,我就隨便舉幾個例子說明吧:

不縮放viewport

(以下說明的rem與px的對應關係都是在螢幕寬度為375px的情況下)

  • 馬蜂窩 1rem = 37.5px

  • 小米 1rem = 52.0833px

  • 小紅書 1rem = 50px

  • 微博

    1rem = 16px 稍微說明下 微博的font-size是根據media query來生成的

縮放viewport

(以下說明的rem與px的對應關係都是在螢幕寬度為375px, viewport scale 0.5的情況下)

vw方案

來了,終於來了!前面說了這麼多關於vw的問題,到底有沒有現有的產品在大規模的使用vw的方案呢?相容方案又是怎麼做的呢?

  • 京東

    京東的移動端首頁採用了vw+rem的佈局方式,元素佈局上依然使用rem單位,沒有縮放viewport, html元素的font-size則使用vw + px fallback的形式,並且使用media query來限制佈局寬度,如下圖所示

    正常情況下:

    京東適配方案 正常情況下
    邊界情況下
    京東適配方案 邊界情況下

  • 網易

    網易的方案和京東基本相同,沒有縮放viewport,使用media query,只處理html元素的font-size,並限制佈局寬度。

  • 餓了麼

    餓了麼也是採用的vw+rem的方案,不過對viewport進行了縮放,也沒有限制佈局寬度,html元素的font-size依然由px指定,但是具體元素的佈局上使用vw + px fallbak的形式,如下圖所示:

餓了麼適配方案

可以看到,使用上述兩種vw+rem的方案對現有的rem方案的改動都不會很大,都採用了vw + fallback的方式,相容性問題得到了保證,只是餓了麼的方案可能更需要構建過程中的外掛支援(關於這個,後面我給你們解釋解釋什麼叫驚喜)。這樣來看,對於大漠老師提出的vw方案中使用viewport-units-buggyfill庫進行相容的做法,我個人就並不是很推薦了,因為該庫使用了css content屬性進行相容處理,官方文件中就指出了對部分瀏覽器的img標籤有影響 ,需要全域性引入一條css規則。且對於需要正常使用content的情況(如:圖示字型)也會引起不可避免的衝突,另外也不支援偽元素的相容。所以從我個人的角度來說,如果你一定要問我使用怎樣的vw適配方案,我會推薦給你上述兩種vw + rem的方案。

rem, vw, 還是...? 各憑本事的移動端適配方案

這就是全部了嗎?

當然不是,我只是列舉了幾個比較典型的移動端適配方案,其實在具體實現的細節上可以自行把握的點還是很多的,適合的終歸才是最好的,那顆銀彈或許不會出現,但我們的手中也從未缺少過利器。

彩(an)蛋(li)部分

相信大多數同學也是有想法在實際開發中把vw融入到現有的移動端適配方案中的。如我上述提到的兩種vw+rem方案,只修改html元素font-size的方案對於已經在使用rem方案的同學來說改動的成本並不大,只需要在原本的media query 裡(或js生成style時)在font-size: *px後面加上font-size: *vw就可以了,如需限制佈局寬度則需多加一點判斷。

而對於餓了麼那種在使用到長度單位時同時輸出rem+vw的方式,肯定是要通過一點額外的外掛來做了。如果你和我一樣剛好在使用Stylus作為css前處理器,那我專門寫了一個Stylus的外掛用來幫你處理這個問題。 這個外掛可以讓你在開發流程使用px書寫css, 和現有的部分外掛不同的是,它同時支援多種適配方案的輸出,目前支援rem,純vw方案以及剛才提到的vw+rem方案的輸出。並且對不希望轉換px的場景做了很方便的處理。也就是說,如果你現在使用rem方案,可以直接替換使用該外掛,當你需要切換到vw或vw+rem方案時基本可以做到無縫切換。

具體的使用方式和示例請參見pandaGao/stylus-px-to-relative-unit

懂我的意思吧

相關文章