viewport移動端適配

黑金團隊發表於2018-11-25

提到viewport移動端適配,那麼心中可能有幾個疑問?

1.為什麼要進行移動端的適配?

2.viewport是什麼?

3.如何進行移動端適配?

一、移動端適配的目的:

通常我們在pc上看到的頁面都是比較大的,在pc上訪問頁面是正常顯示的,預設是不會被縮放的,除非是手動進行了縮放,頁面才會被放大比例或者是縮小比例顯示。但是在移動端是不一樣的,如果將一個pc端的頁面放到手機端進行訪問,那麼可能出現頁面擠到一起、佈局錯亂或者出現橫向滾動條的情況,我們給使用者帶來不好的體驗。還有在螢幕尺寸大小不同的手機上進行訪問頁面時,頁面顯示的效果不能合理的展示,我們期望的是在手機螢幕較大時顯示的內容比較大一些,手機螢幕小的時候頁面的內容也會縮小進行自適應。

因此,移動端適配的目的是在不同尺寸的裝置上,頁面達到合理的展示(自適應)或者說是能夠保持統一效果。

二、viewport的基本概念

1.通常viewport是指視窗、視口,瀏覽器上(也可能是一個app中的webview)用來顯示網頁的那部分割槽域。在移動端和pc端視口是不同的,pc端的視口是瀏覽器視窗區域,而在移動端有三個不同的視口概念:佈局視口、視覺視口、理想視口

  • 佈局視口:在瀏覽器視窗css的佈局區域,佈局視口的寬度限制css佈局的寬。為了能在移動裝置上正常顯示那些為pc端瀏覽器設計的網站,移動裝置上的瀏覽器都會把自己預設的viewport設為980px或其他值,一般都比移動端瀏覽器可視區域大很多,所以就會出現瀏覽器出現橫向滾動條的情況

  • 視覺視口:使用者通過螢幕看到的頁面區域,通過縮放檢視顯示內容的區域,在移動端縮放不會改變佈局視口的寬度,當縮小的時候,螢幕覆蓋的css畫素變多,視覺視口變大,當放大的時候,螢幕覆蓋的css畫素變少,視覺視口變小。

  • 理想視口:一般來講,這個視口其實不是真是存在的,它對裝置來說是一個最理想佈局視口尺寸,在使用者不進行手動縮放的情況下,可以將頁面理想地展示。那麼所謂的理想寬度就是瀏覽器(螢幕)的寬度了。

為了理解起來更清楚一點,在網上找了兩張比較易懂的圖片。如果對這三個視口的概念還不是很清楚,看看下面幾張圖可能就會一目瞭然:

佈局視口

佈局視口

視覺視口

視覺視口

2.那麼如何設定理想視口呢?很簡單,只需要在html的header中加入一段很重要的程式碼

 <meta name="viewport"content="width=device-width,user-scalable=no,initial-scale=1.0,  maximum-scale=1.0,minimum-scale=1.0">	
複製程式碼

這行程式碼大家應該都不陌生,或者說是知道加了這行程式碼,然後頁面的寬度就會跟我的裝置寬度一致。,實際上,它就是設定了理想視口,將佈局視口的寬度設定成了理想視口(瀏覽器/裝置螢幕的寬度)。

上面說到的視口寬度等均是css畫素,所以需要簡單瞭解一下幾個基本的概念:

  • css畫素:程式碼中使用的邏輯畫素,衡量頁面上的內容大小

  • 裝置畫素:即物理畫素,控制裝置顯示的單位,與裝置、硬體有關

  • 裝置獨立畫素:與裝置無關的邏輯畫素,不同於裝置畫素(物理畫素),不是真實存在的。

  • 裝置畫素比:定義裝置畫素與裝置獨立畫素比的關係window.devicePixelRatio)裝置畫素比=物理畫素/裝置獨立畫素

  • 解析度:指的是螢幕上垂直和水平的總物理畫素

3.在meta標籤中,除了viewport這個很重要的屬性,用來設定視口的一些行為,還有幾個與其搭配一起使用的屬性:

屬性 含義 取值
width 定義視口的寬度,單位為畫素 正整數或裝置寬度device-width
height 定義視口的高度,單位為畫素 正整數或device-height
initial-scale 定義初始縮放值 整數或小數
minimum-scale 定義縮小最小比例,它必須小於或等於maximum-scale設定 整數或小數
maximum-scale 定義放大最大比例,它必須大於或等於minimum-scale設定 整數或小數
user-scalable 定義是否允許使用者手動縮放頁面,預設值yes yes/no

三、適配的幾種方案:

(1)css3 媒體查詢:通過媒體查詢的方式,編寫適應不同解析度裝置的的css樣式

@media screen and (max-width: 320px){
    ....適配iphone4的css樣式
}
@media screen and (max-width: 375px){
     ....適配iphone6/7/8的css樣式
}
@media screen and (max-width: 414px){
    ....適配iphone6/7/8 plus的css樣式
}
......
複製程式碼

優點:

  • 方法簡單,只需修改css檔案

  • 調整螢幕寬度時不用重新整理頁面就可以響應頁面佈局

缺點:

  • 程式碼量大,不方便維護

  • 不能夠完全適配所有的螢幕尺寸,需要編寫多套css樣式

(2)百分比佈局方案:給元素設定百分比,例如2個div想佔滿寬度100%,那麼一個div設定寬度為50%,這樣不固定寬度,使得在不同的解析度下都能達到適配

那麼需要清楚一個問題,各個子元素或屬性的百分比是根據誰來設定呢?

  1. 子元素width、height的百分比:子元素的width或height中使用百分比,是相對於子元素的直接父元素
  2. margin和padding的百分比:在垂直方向和水平方向都是相對於直接父親元素的width,而與父元素的height無關
  3. border-radius的百分比:border-radius的百分比是相對於自身寬度,與父元素無關

優點:

  • 寬度自適應,在不同的解析度下都能達到適配

缺點:

  • 百分比的值不好計算
  • 需要確定父級的大小,因為要根據父級的大小進行計算
  • 各個屬性中如果使用百分比,相對父元素的屬性並不是唯一的
  • 高度不好設定,一般需要固定高度

(3)rem方案:

  • rem單位:rem是一個只相對於瀏覽器的根元素(HTML元素)的font-size的來確定的單位。預設情況下,html元素的font-size為12px
  • 通過rem來實現適配:rem單位都是相對於根元素html的font-size來決定大小的,根元素的font-size相當於提供了一個基準,當頁面的寬度發生變化時,只需要改變font-size的值,那麼以rem為固定單位的元素的大小也會發生響應的變化。需要先動態設定html根元素的font-size,再計算出其他頁面元素以rem為固定單位的值

控制font-size的js程式碼

<script type="text/javascript">
    (function() {
        var deviceWidth = document.documentElement.clientWidth;
        deviceWidth = deviceWidth < 320 ? 320 : deviceWidth > 640 ? 640 : deviceWidth;
        document.documentElement.style.fontSize = deviceWidth / 7.5 + 'px';
    })();
</script>
複製程式碼

上面的js程式碼中deviceWidth/7.5,表示font-size用deviceWidth/7.5的值來表示,1rem的值就是deviceWidth/7.5,當視口容器發生變化時就可以動態設定font-size的大小,不論頁面寬度變大還是縮小,視口寬度都會被等分為7.5份,每一份就是1rem,從而1rem在不同的視覺容器中表示不同的大小,但在視口總寬度中的佔比是不變的,實現了等比適配。

這個7.5在這裡並不是一個固定的值,也可以設定為其他值,因為設計稿一般是根據iphone6/7/8的寬度來設計,一般為375或者750,所以為了方便計算,在這裡取7.5,能夠被整除方便後面的計算。

元素的rem值計算

.div{
        display: flex;
        align-items: center;
        justify-content: center;
        width: 2rem;
        height: 0.96rem;
        background:#aaa;
        font-size: 0.24rem;
        
    }
複製程式碼

假定一個div的寬度為100px,那麼在計算時,根據設定的1rem = 50px,所以100px=2rem,其他所有的屬性值都可以類似這樣計算。font-size一般情況下還是使用px,因為在rem中,只要使用了rem單位都會被轉換,那麼在轉換的時候,會出現不能被整除或者出現小數的情況比如10.333333px,那麼在顯示時就可能出現一些偏差。而且如果期望在小螢幕下面顯示跟大螢幕同等量的字型,但是由於rem的等比縮放,在小螢幕下就會存在小螢幕字型更小的情況,所以對於字型的適配更好的做法就是使用px和媒體查詢來進行適配。

優點:

  • rem單位是根據根元素font-size決定大小,只要改變font-size的值,以rem為固定單位的元素大小也會發生響應式的改變

缺點:

  • 必須通過一段js程式碼控制font-size的大小
  • 控制font-size的js程式碼必須放在在頁面第一次載入完成之前,並且放在引入的css樣式程式碼之前。

(4)vw、vh方案 css3中引入與視口有關的新的單位vw和vh,vw表示相對於視口的寬度,vh表示相對於視口高度

單位 含義
vw 相對於視口的寬度,視口寬度是100vw
vh 相對於視口的高度,視口寬度是100vh
vmin vw和vh中較小的值
vmax vw和vh中較大的值

vw單位換算: 視口寬度為100vw佔滿整個視口區域,那麼1vw相當於佔整個視口寬度的1%,所以1px= 1/375*100 vw 所有的頁面元素都可以直接進行計算換算成vw單位,但是這樣計算和百分比方案計算比較類似,都會比較麻煩。

但是有一個比較厲害的外掛—— postcss-px-to-viewport,可以預處理css,將px單位轉換為vw單位,但是需要進行一些相關的webpack配置

{
    loader: 'postcss-loader',
    options: {
    	plugins: ()=>[
        	require('autoprefixer')({
        		browsers: ['last 5 versions']
        	}),
        	require('postcss-px-to-viewport')({
        		viewportWidth: 375,
        		viewportHeight: 1334,
        		unitPrecision: 3,
        		viewportUnit: 'vw',
        		selectorBlackList: ['.ignore', '.hairlines'],
                minPixelValue: 1,
                mediaQuery: false
        	})
    	]
}
複製程式碼

接下來是對postcss-px-to-viewport配置中的屬性的介紹:

單位 含義
viewportWidth 視口寬度(數字)
viewportHeight 視口高度(數字)
unitPrecision 設定的保留小數位數(數字)
viewportUnit 設定要轉換的單位(字串)
selectorBlackList 不需要進行轉換的類名(陣列)
minPixelValue 設定要替換的最小畫素值(數字)
mediaQuery 允許在媒體查詢中轉換px(true/false)

優點:

  • 指定vw\vh相對與視口的寬高,由px換算單位成vw單位比較簡單
  • 通過postcss-px-to-viewport外掛進行單位轉換比較方便

缺點:

  • 直接進行單位換算時百分比可能出現小數,計算不方便

  • 相容性- 大多數瀏覽器都支援、ie11不支援 少數低版本手機系統 ios8、android4.4以下不支援

最後,有一個問題,既然百分比和vw都是需要計算百分比,那麼兩個方案的不同之處?

單位 含義
% width、height等大部分相對於直接父元素、border-radius、translate、background-size等相對於自身
vw 只相對於視口寬度

以上,如有錯漏,歡迎指正!

@Author:lj0214

相關文章