摘要:布局,縮放這也是淘寶使用的方案,根據屏幕寬度設定值,需要適配的元素都使用為單位,不需要適配的元素還是使用為單位。
討論適配方案之前,先了解幾個移動端的概念。
基礎概念設備像素(device pixels):又稱為物理像素,是顯示屏的最小物理單位。在操作系統的調度下,每一個設備像素都有自己的顏色值和亮度值。
設備獨立像素(device independent pixels):基于計算機控制的坐標系統和抽象像素(虛擬像素),由底層系統的程序使用,轉換為物理像素的應用。例如meta里面設置width=device-width,這個device-width就是設備獨立像素。
在chrome里 看到的375x667 320x480等等都是設備獨立像素,其數值上等于CSS像素數組。
設備像素比(device pixel ratio):簡稱dpr,定義了設備像素和設備獨立像素的對應關系,它的值可以按公式得到:設備像素比 = 設備像素/設備獨立像素
目前了解到有三種方法實現適配:
固定高度,寬度自適應
利用rem布局,viewport縮放
vw適配
固定高度,寬度自適應垂直方向用定值,水平方向用百分比、定值、flex都行。這樣設置之后就可以不用管手機屏幕的尺寸進行開發。該方法使用了完美視口:
但是該方法有個缺點,由于高度固定,會導致頁面產生橫向拉伸的視覺效果。
rem布局,viewport縮放這也是淘寶使用的方案,根據屏幕寬度設定 rem 值,需要適配的元素都使用 rem 為單位,不需要適配的元素還是使用 px 為單位。字體也需要通過CSS hack使用px為單位,因為rem可能會導致字體異形或模糊。
下面為手淘源代碼解析:
;(function(win, lib) { var doc = win.document; var docEl = doc.documentElement; var metaEl = doc.querySelector("meta[name="viewport"]"); var flexibleEl = doc.querySelector("meta[name="flexible"]"); var dpr = 0; var scale = 0; var tid; var flexible = lib.flexible || (lib.flexible = {}); //是否已經設置了viewport的meta標簽,若已經設置則根據設置的initial-scale來設置scale和dpr;是否手動設置了dpr,若已經設置則根據設置的initial-dpr或者maximum-dpr來設置scale和dpr if (metaEl) { console.warn("將根據已有的meta標簽來設置縮放比例"); var match = metaEl.getAttribute("content").match(/initial-scale=([d.]+)/); if (match) { scale = parseFloat(match[1]); dpr = parseInt(1 / scale); } } else if (flexibleEl) { var content = flexibleEl.getAttribute("content"); if (content) { var initialDpr = content.match(/initial-dpr=([d.]+)/); var maximumDpr = content.match(/maximum-dpr=([d.]+)/); if (initialDpr) { dpr = parseFloat(initialDpr[1]); scale = parseFloat((1 / dpr).toFixed(2)); } if (maximumDpr) { dpr = parseFloat(maximumDpr[1]); scale = parseFloat((1 / dpr).toFixed(2)); } } } //若沒有手動設置scale或者dpr,則把android的dpr設置為1,ios按照設備的devicePixelRatio 設置。 if (!dpr && !scale) { var isAndroid = win.navigator.appVersion.match(/android/gi); var isIPhone = win.navigator.appVersion.match(/iphone/gi); var devicePixelRatio = win.devicePixelRatio; if (isIPhone) { // iOS下,對于2和3的屏,用2倍的方案,其余的用1倍方案 if (devicePixelRatio >= 3 && (!dpr || dpr >= 3)) { dpr = 3; } else if (devicePixelRatio >= 2 && (!dpr || dpr >= 2)){ dpr = 2; } else { dpr = 1; } } else { // 其他設備下,仍舊使用1倍的方案 dpr = 1; } scale = 1 / dpr; } //html上設置了data-dpr自定義屬性 docEl.setAttribute("data-dpr", dpr); //設置viewport if (!metaEl) { metaEl = doc.createElement("meta"); metaEl.setAttribute("name", "viewport"); metaEl.setAttribute("content", "initial-scale=" + scale + ", maximum-scale=" + scale + ", minimum-scale=" + scale + ", user-scalable=no"); if (docEl.firstElementChild) { docEl.firstElementChild.appendChild(metaEl); } else { var wrap = doc.createElement("div"); wrap.appendChild(metaEl); doc.write(wrap.innerHTML); } } //獲取設備的width,根據width計算出rem具體出,rem代表html的fontSize function refreshRem(){ var width = docEl.getBoundingClientRect().width; if (width / dpr > 540) { width = 540 * dpr; } var rem = width / 10; docEl.style.fontSize = rem + "px"; flexible.rem = win.rem = rem; } // 監聽window的resize和pageshow事件,實現css樣式的重繪 win.addEventListener("resize", function() { clearTimeout(tid); tid = setTimeout(refreshRem, 300); }, false); win.addEventListener("pageshow", function(e) { if (e.persisted) { clearTimeout(tid); tid = setTimeout(refreshRem, 300); } }, false); //判斷document對象是否處于complete狀態,如果完成狀態我們給body一個font-size=12*dpr的值,否則我們判斷dom加載方法來實現body中的font-size的設置。這個設置是為了頁面中字體的大小,而html中的font-size是為了設置頁面的height,width等屬性 if (doc.readyState === "complete") { doc.body.style.fontSize = 12 * dpr + "px"; } else { doc.addEventListener("DOMContentLoaded", function(e) { doc.body.style.fontSize = 12 * dpr + "px"; }, false); } refreshRem(); flexible.dpr = win.dpr = dpr; flexible.refreshRem = refreshRem; flexible.rem2px = function(d) { var val = parseFloat(d) * this.rem; if (typeof d === "string" && d.match(/rem$/)) { val += "px"; } return val; } flexible.px2rem = function(d) { var val = parseFloat(d) / this.rem; if (typeof d === "string" && d.match(/px$/)) { val += "rem"; } return val; } })(window, window["lib"] || (window["lib"] = {}));
總結一下,淘寶使用的方案其實就是做了三點:
動態生成viewport
屏幕寬度設置 rem的大小,即給設置font-size
根據設備像素比(window.devicePixelRatio)給設置data-dpr(css hack用)
設置 rem
例如設計圖給我們的尺寸是7501000的。某個容器在設計圖的寬度是150px225px,那我們在css里面
寬度:150px/750px/10=150px/75px=2rem;
高度為:225px/75px=3rem;
總結一下,布局的時候,各元素的css尺寸=設計稿標注尺寸/設計稿橫向分辨率/10。
設置viewport和data-dpr
這兩個設置都是適配高清屏幕手機的px單位。
縮放是動態的,不同設備下的px顯示一樣的長度。例如設備像素比是2,縮放為0.5,data-dpr為2;設備像素比是3,縮放為0.3333,data-dpr為3。
而data-dpr用法見下圖,字體大小最好通過下面方式設置。
[data-dpr="2"] { font-size: 26px; } [data-dpr="3"] { font-size: 39px; }vw適配
如今vw已經得到了眾多瀏覽器的支持,因此我們可以直接考慮將vw單位運用于我們的適配布局中。
vw是基于Viewport視窗(window.innerWidth/window.innerHeight)的長度單位。
對于viewport概念,可參考文章https://www.w3cplus.com/css/v...
vw、vh與視窗的寬高度關系如下:
1vw等于window.innerWidth的1%
1vh等于window.innerHeight的1%
因此,假設以750px的設計稿為例,100vw = 750px,即1vw = 7.5px。那么我們可以根據設計圖上的px值直接轉換成對應的vw值。我們可以使用PostCSS的插件postcss-px-to-viewport,讓我們可以直接在代碼中寫px。我們可以在一下情境下使用vw
容器適配,可以使用vw
文本的適配,可以使用vw
大于1px的邊框、圓角、陰影都可以使用vw
內距和外距,可以使用vw
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/54618.html
摘要:另一種就是不縮放,對等問題單獨引入處理方案。彩蛋部分相信大多數同學也是有想法在實際開發中把融入到現有的移動端適配方案中的。 前言 2018年最后的法定假期都已經結束了,我相信大部分正在進行或曾經進行過移動端頁面開發的同學都或多或少的了解過使用rem進行移動端頁面適配的方案以及使用vw的方案,(沒了解過的同學可以參見大漠老師的這兩篇文章 使用Flexible實現手淘H5頁面的終端適配和再...
摘要:另一種就是不縮放,對等問題單獨引入處理方案。彩蛋部分相信大多數同學也是有想法在實際開發中把融入到現有的移動端適配方案中的。 前言 2018年最后的法定假期都已經結束了,我相信大部分正在進行或曾經進行過移動端頁面開發的同學都或多或少的了解過使用rem進行移動端頁面適配的方案以及使用vw的方案,(沒了解過的同學可以參見大漠老師的這兩篇文章 使用Flexible實現手淘H5頁面的終端適配和再...
摘要:隨著移動端的發展,在手機上看電腦端的頁面已成為非常普及現象。方案一固定高度,使其寬度自適應這也是我接觸移動端適配第一次使用的方案。 不知不覺做前端已經兩年了,從PC端,移動端,微信小程序一路走來到今天剛剛開放注冊的快應用(手機廠商對抗小程序的新技能,所以在注冊時用的是qq郵箱的話要去垃圾箱里才能找到注冊郵件),對于前端圈日新月異的磅礴發展對于大前端發展是喜聞樂見的,這次的快應用的手機廠...
摘要:隨著移動端的發展,在手機上看電腦端的頁面已成為非常普及現象。方案一固定高度,使其寬度自適應這也是我接觸移動端適配第一次使用的方案。 不知不覺做前端已經兩年了,從PC端,移動端,微信小程序一路走來到今天剛剛開放注冊的快應用(手機廠商對抗小程序的新技能,所以在注冊時用的是qq郵箱的話要去垃圾箱里才能找到注冊郵件),對于前端圈日新月異的磅礴發展對于大前端發展是喜聞樂見的,這次的快應用的手機廠...
閱讀 2312·2021-09-26 10:21
閱讀 2785·2021-09-08 09:36
閱讀 3065·2019-08-30 15:56
閱讀 954·2019-08-30 12:57
閱讀 916·2019-08-26 10:39
閱讀 3554·2019-08-23 18:11
閱讀 3077·2019-08-23 17:12
閱讀 1070·2019-08-23 12:18