移動端適配問題解決方案

前言

隨着時間的發展,如今基本上人手一部手機的低頭族。作爲前端開發的程序猿,在開發移動端web應用的時候,對面一堆各色尺寸不同的屏幕,就有點淡淡的憂傷。 css

已上是2018年二月份最新的友盟數據,可在 這裏查看詳情

很明顯咱們所要實現的就是在上述如此之多的屏幕,都能實現UI大大出的視覺圖上的效果。而要實現這樣的效果主要有兩個難點html

  1. 各屏幕適配
  2. Retina屏下的細節處理(主要是1px的問題)

各屏幕適配

各屏幕的適配,有兩種方案,flexible + remvw。這三個單詞是什麼意思,看着很眼熟,可是這兩個方案竟然是什麼呢,請容許我細細道來。前端

flexible + rem

顯而易見,該方案是由rem 以及 flexible組成的。rem (font size of the root element)相對於根元素(即html元素)font-size計算值的倍數,flexible 即 flexible.js, 手淘團隊提供的一個爲該方案屏幕適配而寫的一個庫,主要實現的功能就是,根據屏幕的寬度給 html 元素設置一個合適的 font-size 值。vue

怎麼樣看的不是很懂是吧。讓我來用一個頁面場景再複述一遍。html5

正常狀況下,咱們的UI大大會以iphone6的尺寸爲標準,作一套視覺效果圖,並在上面進行標註,給到咱們的標註圖,以下所示react

拿到這個圖 咱們該如何下手呢webpack

  1. 先設置 html 元素的 font-size, 這個值咱們暫時設置爲 font-size: 37.5px,即1rem = 37.5px;
  2. 以iphone6爲例子,其屏幕寬度爲 750px, 整個屏幕的寬度即 20rem = 37.5 * 20px = 750px;
  3. 此時手機號的輸入框爲 490px = 13.06777777rem
  4. 依次將頁面上的px轉換爲rem,這樣咱們就獲得了全是rem爲尺寸單位的頁面

到這裏爲止是否是就結束了呢 ? 很遺憾的告訴你並非。爲何 html 元素的 font-size 要設置爲 37.5px呢?如今這個界面在iphone6上能完美顯示了,在iphone5s,iphone6p能完美顯示嗎?(iphone6, iphone6s, iphone7. iphone8屏幕沒有發生變化,本文直接用iphone6代替了。) 上面的兩個問題 咱們還有沒解決,這個時候就輪到flexible登場了。只須要像以下引入就可實現用js來自動根據屏幕寬度設置 html元素的font-size的值。git

<script src="http://g.tbcdn.cn/mtb/lib-flexible/0.3.4/??flexible_css.js,flexible.js"></script>
複製代碼

引伸一下

在上述過程當中,你會發現,UI給到咱們的通常是px標註的圖,咱們將其轉化爲rem,這個過程其實會花費很大的計算時間。作爲一個合格的程序員,咱們應該把這種機械性無腦的操做交給計算機來實現。我使用的是PostCss的插件 postcss-px2rem,這個插件能讓咱們在寫代碼時候直接寫px,在構建的時候自動將咱們所寫的px轉換爲rem,大大提高了咱們的開發效率。程序員

vw

這個vw的方案,至關而言還比較新。vw 即(viewport width)可視窗口的寬度。之因此把這個方案放在後面來講,是由於viewport在去年(2017年)的時候存在很多的兼容性問題,各個瀏覽器的支持並非很好。可是來到了2018年這個時間點,viewport單位意見獲得了衆多瀏覽器的支持(80.45%)。 github

能夠在 這裏查看。

接下來就讓咱們來正式瞭解下這個方案吧。 vw既然是一個尺寸單位,那它的寬度等於多少呢?等於1%整個屏幕的寬度。舉個例子,再次以iphone6手機爲例,100vw = 750px => 1vw = 7.5px

再一次那上次的界面作示範

  1. 根據定義,咱們瞭解了在iphone6手機上 1vw = 7.5px
  2. 此時手機號的輸入框爲 490px = 65.333333vw
  3. 依次將頁面上的px轉換爲vw,這樣咱們就獲得了全是vw爲尺寸單位的頁面

到這裏爲止是否是就結束了呢? 是的就是這麼簡單。

引伸一下

跟以前同樣的痛點,咱們仍然須要花費大量沒必要要的計算時間去把標註圖中的px轉換爲vw,有沒有相似於postcss-px2rem的工具呢?很榮幸能再次站在巨人的肩膀上,已經有大神寫了了相似的PostCss插件 postcss-px-to-viewport

1px問題

移動端的屏幕不只僅分辨率有差別,其實還有Retina屏的問題。正常狀況下,咱們代碼裏的1px在屏幕上就應該顯示一個像素點,可是在Retina屏下則不只僅是一個像素點。再次拿iphone6爲例,其dpr(device pixel ratio)設備像素比爲2,css中一個1x1的點,其實在iphone6上是2x2的點,而且1px的邊框在devicePixelRatio = 2的Retina屏下會顯示成2px,在iPhone6 Plus下甚至會顯示成3px。

這樣的話,咱們就會發如今有些手機上1px明顯跟另外的一些手機的1px粗細不同。 其實大多數的小公司不會扣這樣的一個細節,好比說咱們公司不會。(^__^) 嘻嘻……

可是做爲一個有追求的前端工程師,咱們應該儘可能的把事情作的完美一點,(ps.像大公司看齊,在大公司這個細節問題實際上是不容忽視的,爲了本身之後的發展前途,咱們有必要把這個細節完善掉的。)

這個問題的解決方案有不少,我的以爲最簡單方面的仍是大漠大大的一種解決方案。使用postcss-write-svg插件,

@svg 1px-border {
  height: 2px;
  @rect {
    fill: var(--color, black);
    width: 100%; height: 50%;
    }
  }
.example {
  border: 1px solid transparent;
  border-image: svg(1px-border param(--color #00b1ff)) 2 2 stretch;
}
複製代碼

編譯出來就是

.example {
  border: 1px solid transparent;
  border-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' height='2px'%3E%3Crect fill='%2300b1ff' width='100%25' height='50%25'/%3E%3C/svg%3E") 2 2 stretch;
}
複製代碼

其餘

小程序中的屏幕適配

最近在寫小程序,在小程序裏,使用的是小程序的那套,跟平時用的vue全家桶以及react全家桶不同,並無配置webpack,在這種狀況下咱們使用postcss其實很困難(反正我是搞不出來/(ㄒoㄒ)/~~)

那該怎麼辦呢,小程序提供了一個本身的單位, rpx(responsive pixel): 能夠根據屏幕寬度進行自適應。規定屏幕寬爲750rpx。如在 iPhone6 上,屏幕寬度爲375px,共有750個物理像素,則750rpx = 375px = 750物理像素,1rpx = 0.5px = 1物理像素。

設備 rpx換算px (屏幕寬度/750) px換算rpx (750/屏幕寬度)
iPhone5 1rpx = 0.42px 1px = 2.34rpx
iPhone6 1rpx = 0.5px 1px = 2rpx
iPhone6p 1rpx = 0.552px 1px = 1.81rpx

咱們直接用拿到iphone6的標註圖,直接寫rpx就好。棒👍

總結

若是仔細看一下的話,會發現以前的rem的方案其實就是模擬了vw的實現方案,二者有很是多的類似之處。在lib-flexible的github上有着這樣的一句話。

因爲viewport單位獲得衆多瀏覽器的兼容,lib-flexible這個過渡方案已經能夠放棄使用,不論是如今的版本仍是之前的版本,都存有必定的問題。建議你們開始使用viewport來替代此方案。vw的兼容方案能夠參閱《如何在Vue項目中使用vw實現移動端適配》一文。

咱們能夠獲得一個很明確的信息,lib-flexible這個方案已經被放棄使用了,咱們能夠去擁抱vw的那套實現方案。

本文參考了大漠大大在 www.w3cplus.com 裏的多篇文章

  1. 使用Flexible實現手淘H5頁面的終端適配
  2. 再聊移動端頁面的適配
  3. 走向視網膜(Retina)的Web時代
  4. 再談Retina下1px的解決方案
  5. 小程序-wxss
相關文章
相關標籤/搜索