基於REM的移動端響應式適配方案

来源:http://www.cnblogs.com/unclekeith/archive/2017/07/06/7129093.html
-Advertisement-
Play Games

視口 在前一段時間,我曾經寫過一篇關於viewport的文章。最近由於在接觸移動端開發,對viewport有了新的理解。於是,打算重新寫一篇文章,介紹移動端視口的相關概念。 關於這篇文章說到的所有知識,本質上離不開以下代碼 瞭解過移動端開發的朋友,其實對以上的代碼就不會陌生。上面的代碼,主要涉及到m ...


視口

在前一段時間,我曾經寫過一篇關於viewport的文章。最近由於在接觸移動端開發,對viewport有了新的理解。於是,打算重新寫一篇文章,介紹移動端視口的相關概念。

關於這篇文章說到的所有知識,本質上離不開以下代碼

<meta name="viewport" content="width=device-width, initial-scala=1, maximum-scale=1, minimum-scale=1, user-scalable=no" />

@media all and (max-width: 320px) {
    // do something
}

瞭解過移動端開發的朋友,其實對以上的代碼就不會陌生。上面的代碼,主要涉及到meta視口標簽與媒體查詢。單單以上簡短的代碼就需要明白:

  • 像素(pixel)
  • 視口(viewport)
  • 解析度(resolution)
  • meta視口標簽
  • 媒體查詢(media query)
  • JavaScript相關的屬性和方法
  • 如何實現移動端響應式適配的問題

那就進入主題吧:)

像素

在移動端上,所謂的像素分為兩種

  • CSS像素:CSS像素就是我們在編寫CSS代碼時的像素。
  • 設備像素:設備屏幕的物理像素,任何設備的物理像素的數量都是固定的。

1個CSS像素等於多少個設備像素取決於屏幕特性(是否是高清屏)和用戶縮放的比例。當用戶將屏幕從100%放大到200%時,1個CSS像素等於2個設備像素,反之相反;當屏幕為Retina高清屏(如iPhone6,dpr=2)時,1個CSS像素就等於2個設備像素,反之相反。

需要明白一點的是,2個設備像素並不是說它擴大了兩倍,而是說在頁面上仍然顯示的是1px(1個CSS像素),但是這1px是由2個設備像素組成。像素點變多了,因此圖像會變得更加清晰。下麵這幅圖大致說明瞭CSS像素和設備像素的區別。

視口

在移動端上,存在三種不同的視口。

  • 佈局視口:在PC端上,佈局視口等於瀏覽器視窗的寬度。而在移動端上,由於要使為PC端瀏覽器設計的網站能夠完全顯示在移動端的小屏幕里,此時的佈局視口會遠大於移動設備的屏幕。在移動端,預設情況下,佈局視口等於瀏覽器視窗寬度。佈局視口限制了CSS的佈局。JavaScirpt上獲取佈局視口的寬度可以通過document.documentElement.clientWidth | document.body.clientWidth得到。
  • 視覺視口:視覺視口是用戶正在看到的區域。用戶可以縮放來操作視覺視口,而不影響視覺視口的寬度。視覺視口決定了用戶看到了什麼。在JavaScript上獲取視覺視口的寬度可以通過`window.innerWidth得到。

在PC端上,視覺視口等於佈局視口的寬度,無論用戶是放大屏幕還是縮小屏幕,這兩個視口的寬度仍然相等。但是,在移動端上,並非如此。縮放屏幕的過程實質上就是CSS像素縮放的過程。當用戶將屏幕放到到兩倍時,視覺視口變小了(因為視覺視口中CSS像素變少了),而每單位的CSS像素卻變大了,因此1px(1個CSS像素)等於2個設備像素。同理,當為iPhone6(dpr=2)時,視覺視口中CSS像素變少了,但是1px等於2個設備像素。當用戶縮小屏幕時也是同樣的道理。縮放的過程並不會影響佈局視口的大小。

也就是說,高清屏(dpr>=2)或屏幕放大時,視覺視口變小(CSS像素變少),每單位的CSS像素等於更多的設備像素;非高清屏(dpr<2)
或屏幕縮小時,視覺視口變大(CSS像素變多),每單位的CSS像素等於更少的設備像素。
但是無論放大或縮小屏幕,佈局視口的寬度仍然保持不變。

  • 理想視口:由於預設情況下佈局視口等於瀏覽器視窗寬度,因此在移動端上需要通過放大或縮小視覺視口來查看頁面內容,這當然體驗糟糕啊!因此在移動端引入了理想視口的概念。理想視口的出現必須需要設置meta視口標簽,此時佈局視口等於理想視口的寬度。常見的,iPhone6的理想視口為375px * 667px,iPhon6 plus的理想視口為414px * 736px。在JavaScript上獲取視覺視口的寬度window.screen.width得到。

    <meta name="viewport" content="width=device-width" />

    當設置了meta視口標簽之後,iPhone6的佈局視口寬度將等於375px,iPhone6plus佈局視口的寬度等於414px。其他移動設備相似。

理想視口會隨著屏幕的旋轉而改變。當iPhone6為肖像模式時(即豎屏),此時理想視口為375px * 667px;但為橫屏模式時,此時理想視口為667px * 375px。

解析度與設備像素比

解析度是指每英寸內點的個數,單位是dpi或者dppx。設備像素比是指設備像素與理想視口寬度的比值,沒有單位。

解析度在CSS上可以通過resolution屬性設置。一般情況下會使用dpi作為解析度的單位,因為dppx並非所有瀏覽器都支持。

而設備像素比在CSS上可以通過device-device-pixel-ratio屬性設置,而在JavaScript上可以通過window.devicePixelRatio屬性獲取。

同時,1dpr=96dpi。舉個例子。在iPhon6下,理想視口寬度為375px,而設備像素為750px,因此此時設備像素比為2,解析度為192dpi。因此如果為iPhon6以下的設備寫某個特定樣式,可以這樣寫

// 註意,device-pixel-ratio需要帶上-webkit-首碼,保證瀏覽器相容性問題。
@media all and (max-width: 375px) and (-webkit-max-device-pixel-ratio: 2) {
    body {
        background-color: red;
    }
}
或者
@media all and (max-width: 375px) and (max-resolution: 192dpi) {
    body {
        background-color: red;
    }
}

meta視口標簽

meta視口標簽是是設置理想視口的重要元素,主要用於將佈局視口的尺寸和理想視口的尺寸相匹配。meta視口標簽存在5個指令

  1. width:設置佈局視口的寬度,一般設為device-width。
  2. initial-scale:初始縮放比例。1即100%,2即200%,以此類推
  3. maximum=scale:最大縮放比例。
  4. minimum-scale:最小縮放比例。
  5. user-scalable:是否靜止用戶進行縮放,預設為no。

需要註意的是,縮放是根據理想視口進行計算的。縮放程度與視覺視口的寬度是逆相關的。也就是說,當你將屏幕放到到2倍時,視覺視口為理想視口的一半,此時每單位的CSS像素等於2個設備像素。縮小時則相反。

響應式適配問題

理解了一些基本概念之後,我們來看看如何實現響應式適配。

一般情況下,前端開發工程師會根據設計師給的設計稿進行開發。而設計稿一般是根據iPhon6手機進行頁面的設計的。我們知道iPhone6的理想視口寬度為375px,同時iPhone6的設備像素比為2,設備像素為750px。我們需要在只有一份設計稿的情況下寫出適應各種屏幕不一的終端設備,因此需要一些移動端響應式適配的方案。此時需要用到的一個單位是REM。簡單的說,REM會根據HTML元素的font-size進行設置。當HTML元素的font-size: 16px時,1rem = 16px, 1.5rem = 24px

個人總結出了兩套響應式適配的方案(前提是設置meta視口標簽)。兩套方案由一個共同點:給定一個基準值

假如現在拿到的設計稿是根據iPhone6進行設計的。

方案一

方案一是設計稿給什麼尺寸,我們就將其縮小100倍,最後換算成rem單位。比如,設計稿上某個title的font-size為32px,此時寫CSS樣式時就直接縮小100倍,即0.32rem

由於rem是根據根元素進行設置的,所以我們需要設置根元素的font-size

給HTML設置font-size的基本思路:

  1. 通過window.screen.width獲取不同移動設備的理想視口寬度。
  2. 規定基準值為750px(此值為iPhon6的設備像素)。
  3. (1) / (2) * 100即得到HTML元素的font-size。(乘於100是因為我們在前面將字體縮小了100倍,此時要乘回來)

換算成公式即:設計稿尺寸 / 100 * (不同設備的理想視口寬度 / 基準值 * 100)

舉個例子。

// 根據不同設備的理想視口寬度動態設置根元素的`font-size`。
let idealViewWidth = window.screen.width;
const BASICVALUE = 750;
document.documentElement.style.fontSize = (idealViewWidth / BASICVALUE) * 100 + 'px';

因此,在不同設備下的HTML元素的font-size大小和實際像素如下

iPhone5 : (320 / 750) * 100 = 42.667px
iPhone6 : (375 / 750) * 100 = 50px
iPhone6+: (414 / 750) * 100 = 55.2px

假如設計稿上標註.title類上的字體為32px,此時有
iPhone5上的某字體:  42.667 * 0.32rem = 13.653px
iPhone6上的某字體: 50 * 0.32rem = 16px
iPhone6+上的某字體: 55.2 * 0.32rem = 17.664px

可以看出,在不同設備下,同一字型大小的字體使用rem單位可以實現不同設備的響應式適配。不單單在字體上可以使用,在移動端上的width、height等涉及單位的都可以使用。這樣的話,就可以在不同設備下完美的復現設計稿的要求。

方案二

此方案使用了SASS預處理器。基本思路:

  1. 設置根元素的font-size。通過獲取不同設備的理想視口寬度,再除以10。(除以10是因為不想font-size太大。)
  2. 給定基準值,此時給的基準值為75px(此值為iPhone6的設備像素除以10)
  3. 寫SASS Function

代碼如下

SASS
@function px2rem ($value) {
    $para: 75px;
    @return $value / $para + rem;
}

JS
let idealViewWidth = window.screen.width;
document.documentElement.style.fontSize = idealViewWidth / 10 + 'px';

在不同設備下根元素的`font-size`:

iPhone5 : 320px / 10 = 32px
iPhone6 : 375px / 10 = 37.5px
iPhone6+: 414px / 10 = 41.4px

根據以上,可以看一個例子。某設計稿下5個li,橫向排布,每個的寬度為200px
CSS
@import (路徑名)
iPhone5: li { width: px2rem(200px) } => width: 85.333px
// 此時(200px / 75px = 2.667rem) 2.667rem = 2.667 * (320 / 10) = 85.3333px
iPhone6: li { width: px2rem(200px) } => width: 100px
// 此時(200px / 75px = 2.667rem) 2.667rem = 2.667 * (375 / 10) = 100px
iPhone6+: li { width: px2rem(200px) } => width: 4138px
// 此時(200px / 75px = 2.667rem) 2.667rem = 2.667 * (414 / 10) = 110.4138px

因此,一個200px的(實際只有100px)的li元素的寬度在不同設備下顯示了不同的寬度,實現了響應式適配的問題。

方案三

方案三與前兩個方案不相同,此方案並不需要給根元素設置font-size,不需要基準值。此方案是根據不同設備的dpr來實現頁面的縮放的。

基本思路如下:

  1. 通過window.devicePixelRatio獲取設備的dpr
  2. 根據不同的dpr縮放頁面,動態設置meta視口標簽。(縮放是放大或縮小CSS的過程,根據理想視口進行縮放,與視覺視口方向相反)

代碼如下:

let dpr = window.devicePixelRatio;
let meta = document.createElement('meta');
let initialScale = 1 / dpr;
let maximumScale = 1 / dpr;
let minimumScale = 1 / dpr;
meta.setAttribute('name', 'viewport');
meta.setAttribute('content', `width=device-width, user-scalable=no, initial-scale=${initialScale}, maximum-scale=${maximumScale}, minimum-scale=${minimumScale}`);
document.head.appendChild(meta);

因此,可以直接根據設計稿的尺寸寫CSS樣式,如設計稿下有5個li元素,寬度為200px,此時不同設備下li的寬度

iPhone5 : li { width: 200px } 實際寬度為:100px
iPhone6 : li { width: 200px } 實際寬度為:100px
iPhone6+: li { width: 200px } 實際寬度為:66.667px

以上三種方法解決了大部分移動端響應式適配的問題,但是在1px問題上,使用以上的方法仍然(除了第三個方案),都不能很好的解決1px的問題。有時間寫一篇文章介紹如何解決1px的問題。

當然..關於移動端響應式適配還有許多好的解決方法,希望留言同大家分享:)


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 5.領域模型設計 在開始考慮如何構建賬戶子系統的領域模型之前,我們先來看看關於CA里領域模型的基本概念。初次接觸這些陌生的概念確實會一知半解,不過沒有關係,大家實踐幾次領域設計後就會融會貫通,深刻體會到這些概念背後隱藏的優點。 概念1:領域對象。領域模型里的一切對象都應該是領域對象。所謂的領域對象就 ...
  • 4.劃分子系統 使用CA編碼項目的核心結構是:由多個子系統組成多個不同的服務來提供項目的各種功能。請不要將這裡提到的子系統與大家在別的項目實施方法里的概念混為一談,CA里的子系統概念是完全不一樣的,下麵我們詳細闡述這一點。 同一事物在不同領域里的本質特征是不盡相同的,例如書在銷售領域的關註點是價格、 ...
  • 前言: 目前絕大多數公司依然採用的是傳統的項目實施方式——圍繞資料庫設計做應用程式開發。在這種方式下,程式員的主要工作就是不斷的增刪改查各種數據表,以數據為核心驅動系統的運行。隨著項目進度的推進,系統暴露的問題卻越來越多,程式員每天陷入無止境的修複狀態中,增加或修改一個功能的代價也越來越大。項目進展 ...
  • 首先推上神器 jPlayer : 基於HTML5/Flash的音頻、視頻播放器 jPlayer是一個JavaScript寫的完全免費和開源 (MIT) 的jQuery多媒體庫插件 (現在也是一個Zepto插件); jPlayer可以讓你迅速編寫一個跨平臺的支持音頻和視頻播放的網頁. jPlayer的 ...
  • 在javascript開發過程中,我們不可避免的會遇到一些非同步編程的情景,無論是前端的ajax請求還是,node的各種非同步api,下文是在工作學習過程中總結的關於javascript非同步編程集中常見方式用法的總結 回調函數 使用回調函數是最常見的一種形式 //jQuery ajax $.get('t ...
  • HTTP(HyperText Transfer Protocol)是一套電腦通過網路進行通信的規則。電腦專家設計出HTTP,使HTTP客戶(如Web瀏覽器)能夠從HTTP伺服器(Web伺服器)請求信息和服務,HTTP目前協議的版本是1.1.HTTP是一種無狀態的協議,無狀態是指Web瀏覽器和We ...
  • [1]導入 [2]data屬性 [3]API [4]過渡效果 ...
  • 具體代碼如下: ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...