適用於移動設備彈性布局的js腳本(rem單位)


背景介紹

目前,隨着移動設備的普及和4G網絡的普及,web在移動端的占比已經遠遠超過PC端,各種H5頁面推廣頁面,H5小游戲熱度火爆。以前簡單的使用px單位(沒有彈性)的時代已經無法滿足各位設計師和用戶了。如何100%還原UI設計師的設計圖,一直困擾着前端工程師。

css單位

學習首先我們簡單了解下css目前都支持哪些單位:

  • px: 設置固定的布局或者元素大小,缺點是沒有彈性
  • em: 參考父元素的font-size,em會繼承父級元素的字體大小,em的值並不是固定的
  • rem: 相對根元素html的font-size
  • %: 相對父元素,對於position: absolute;的元素是相對於已定位的父元素,對於position: fixed;的元素是相對於ViewPort(可視窗口)
  • vw: view width的簡寫, 是指可視窗口的寬度,瀏覽器寬度1200px, 1 vw = 1200px/100 = 12 px
  • vh: view height的簡寫,是指可視窗口的高度,瀏覽器高度900px, 1 vh = 900px/100 = 9 px
  • vm: 相對於視口的寬度或高度中較小的那個, 其中最小的那個被均分為100單位的vm,瀏覽器高度900px,寬度1200px,取最小的瀏覽器高度,1 vm = 900px/100 = 9 px
  • in: 寸
  • cm: 厘米
  • mm: 毫米
  • pt: point, 大約1/72寸
  • pc: pica, 大約6pt, 1/6寸

具有彈性布局能力的單位:

  • em,%: 相對於父元素
  • rem: 相對於html
  • vw, vh, vm: 相對於可視窗口

從上可以看出,要做頁面整體彈窗縮放的話,使用rem, vm, vw, vh更適合,因為任何內容都可以找到同一個基准。

HTML viewport基礎

概念

viewport 是用戶網頁的可視區域。

手機瀏覽器是把頁面放在一個虛擬的"窗口"(viewport)中,通常這個虛擬的"窗口"(viewport)比屏幕寬,這樣就不用把每個網頁擠到很小的窗口中(這樣會破壞沒有針對手機瀏覽器優化的網頁的布局),用戶可以通過平移和縮放來看網頁的不同部分。

用法

<meta name="viewport" content="width=device-width, initial-scale=1.0">

屬性說明

  • width:控制 viewport 的大小,可以指定的一個值,如 600,或者特殊的值,如 device-width 為設備的寬度(單位為縮放為 100% 時的 CSS 的像素)。
  • height:和 width 相對應,指定高度。
  • initial-scale:初始縮放比例,也即是當頁面第一次 load 的時候縮放比例,默認值1。
  • maximum-scale:允許用戶縮放到的最大比例。
  • minimum-scale:允許用戶縮放到的最小比例。
  • user-scalable:用戶是否可以手動縮放。

彈性布局方案

通過以上可以看出,使用彈性布局的css單位配合設置html viewport元信息,就可以實現整體頁面的彈性布局(包含字體大小)。

先弄明白幾個概念:

設備分辨率:一個物理像素是顯示器(手機屏幕)上最小的物理顯示單元,在操作系統的調度下,每一個設備像素都有自己的顏色值和亮度值;
設備屏幕寬度:設備顯示器的實際寬度;
DPR:設備上物理像素和設備獨立像素(device-independent pixels (dips))的比例,DPR = 設備分辨率/設備屏幕寬度;
300ppi:每英寸300個像素點

思路

根據以上的概念,那么,我們知道

window.devicePixelRatio = document.body.clientWidth / window.screen.width;


如果屏幕分辨率寬是1080px,屏幕寬度為360px,那么DPR=1080/360=3。

如果現在UI設計圖也是1080px,那么前端工程師不想丟失任何細節的使用代碼如何還原呢?

可以設置屏幕寬度為1080px, 設置viewport屬性initial-scale = 1/3;

這樣360px的屏幕就可以容納1080px寬的內容了。

但是每個手機的分辨率都不一樣,那么如何來設置這個這個initial-scale呢?我們可以通過以下方式:

var scale = 1 / window.devicePixelRatio;
document.querySelector('meta[name="viewport"]').setAttribute('content', 'user-scalable=no,initial-scale=' + scale + ', maximum-scale=' + scale + ', minimum-scale=' + scale);


將user-scalable設置為no, 不允許縮放,有縮放需要的,可以不設置

之后如何設置某一個區塊的寬,高,或者字體大小呢?

我們還需要設置html標簽,字體的大小,我習慣於使用設計圖的寬/20來獲取元素的rem數值。比如

  • UI設計圖文字大小30px, 那么我習慣使用 font-size: 1.5rem;
  • UI設計圖圖片寬100px, 我習慣使用 width: 5rem;

那么我會設置html的font-size為 deviceWidht / (UI設計圖寬/20);

var base = 720 / 20; // 720為UI設計稿的寬
var fontSize = deviceWidth / base;
document.documentElement.style.fontSize = fontSize + 'px';

 

結合以上,完整代碼為:

<script type="text/javascript">
var scale = 1 / window.devicePixelRatio;
document.querySelector('meta[name="viewport"]').setAttribute('content', 'user-scalable=no,initial-scale=' + scale + ', maximum-scale=' + scale + ', minimum-scale=' + scale);
window.onresize = function (base) {
  var deviceWidth = (document.body.clientWidth < document.documentElement.clientWidth) ? document.body.clientWidth : document.documentElement.clientWidth;
  var screenWidth = window.screen.width;
  if (deviceWidth / screenWidth != window.devicePixelRatio) {
    document.querySelector('meta[name="viewport"]').setAttribute('content', 'width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no');
    deviceWidth = (document.body.clientWidth < document.documentElement.clientWidth) ? document.body.clientWidth : document.documentElement.clientWidth;
  }
  var fontSize = deviceWidth / base;
  document.documentElement.style.fontSize = fontSize + 'px';
};
window.onresize(720);
</script>

以上代碼我放在<head>里面,在html標簽渲染前就開始設置。

一開始就根據DPR設置initial-scale,之后在onresize里面設置html字體大小。

大家會注意到onresize里面有這樣一段代碼:

var deviceWidth = (document.body.clientWidth < document.documentElement.clientWidth) ? document.body.clientWidth : document.documentElement.clientWidth;
var screenWidth = window.screen.width;
if (deviceWidth / screenWidth != window.devicePixelRatio) {
  document.querySelector('meta[name="viewport"]').setAttribute('content', 'width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no');
  deviceWidth = (document.body.clientWidth < document.documentElement.clientWidth) ? document.body.clientWidth : document.documentElement.clientWidth;
}

這一段代碼是為了兼容一部分舊款機器,這些機器無法正常的獲取到DPR值,那么我們就只能設置屏幕頁面內容寬度為設備寬度。


有疑問,歡迎聯系博主討論。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM