HTML網頁樣式根據手機分辨率自適應
轉自:https://blog.csdn.net/u010071211/article/details/80474286
問題:不同手機型號屏幕尺寸大不相同,導致同樣的文字,有的顯示一行,有的顯示多行。
通過查資料和自己的嘗試解決;網頁開發習慣的px單位,手機html開發不適用。
源代碼如下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <!--防止手機頁面縮放--> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no"> <title>Document</title> </head> <body> <!-- 文字單位設置為rem即可,通過微信開發者工具切換手機型號查看效果。 --> <div style='border:1px red solid;border-radius:100px;font-size:1rem;'>測試手機端文字的自適應</div> </body> <script> /* 利用js計算當前設備的DPR,動態設置在html標簽上,並動態設置html的font-size,*/ !function (win, lib) { var timer, doc = win.document, docElem = doc.documentElement, vpMeta = doc.querySelector('meta[name="viewport"]'), flexMeta = doc.querySelector('meta[name="flexible"]'), dpr = 0, scale = 0, flexible = lib.flexible || (lib.flexible = {}); // 設置了 viewport meta if (vpMeta) { console.warn("將根據已有的meta標簽來設置縮放比例"); var initial = vpMeta.getAttribute("content").match(/initial\-scale=([\d\.]+)/); if (initial) { scale = parseFloat(initial[1]); // 已設置的 initialScale dpr = parseInt(1 / scale); // 設備像素比 devicePixelRatio } } // 設置了 flexible Meta else if (flexMeta) { var flexMetaContent = flexMeta.getAttribute("content"); if (flexMetaContent) { var initial = flexMetaContent.match(/initial\-dpr=([\d\.]+)/), maximum = flexMetaContent.match(/maximum\-dpr=([\d\.]+)/); if (initial) { dpr = parseFloat(initial[1]); scale = parseFloat((1 / dpr).toFixed(2)); } if (maximum) { dpr = parseFloat(maximum[1]); scale = parseFloat((1 / dpr).toFixed(2)); } } } // viewport 或 flexible // meta 均未設置 if (!dpr && !scale) { // QST // 這里的 第一句有什么用 ? // 和 Android 有毛關系 ? var u = (win.navigator.appVersion.match(/android/gi), win.navigator.appVersion.match(/iphone/gi)), _dpr = win.devicePixelRatio; // 所以這里似乎是將所有 Android 設備都設置為 1 了 dpr = u ? ((_dpr >= 3 && (!dpr || dpr >= 3)) ? 3 : (_dpr >= 2 && (!dpr || dpr >= 2)) ? 2 : 1 ) : 1; scale = 1 / dpr; } docElem.setAttribute("data-dpr", dpr); // 插入 viewport meta if (!vpMeta) { vpMeta = doc.createElement("meta"); vpMeta.setAttribute("name", "viewport"); vpMeta.setAttribute("content", "initial-scale=" + scale + ", maximum-scale=" + scale + ", minimum-scale=" + scale + ", user-scalable=no"); if (docElem.firstElementChild) { docElem.firstElementChild.appendChild(vpMeta) } else { var div = doc.createElement("div"); div.appendChild(vpMeta); doc.write(div.innerHTML); } } function setFontSize() { var winWidth = docElem.getBoundingClientRect().width; if (winWidth / dpr > 540) { (winWidth = 540 * dpr); } // 根節點 fontSize 根據寬度決定 var baseSize = winWidth / 10; docElem.style.fontSize = baseSize + "px"; flexible.rem = win.rem = baseSize; } // 調整窗口時重置 win.addEventListener("resize", function () { clearTimeout(timer); timer = setTimeout(setFontSize, 300); }, false); // 這一段是我自己加的 // orientationchange 時也需要重算下吧 win.addEventListener("orientationchange", function () { clearTimeout(timer); timer = setTimeout(setFontSize, 300); }, false); // pageshow // keyword: 倒退 緩存相關 win.addEventListener("pageshow", function (e) { if (e.persisted) { clearTimeout(timer); timer = setTimeout(setFontSize, 300); } }, false); // 設置基准字體 if ("complete" === doc.readyState) { doc.body.style.fontSize = 12 * dpr + "px"; } else { doc.addEventListener("DOMContentLoaded", function () { doc.body.style.fontSize = 12 * dpr + "px"; }, false); } setFontSize(); flexible.dpr = win.dpr = dpr; flexible.refreshRem = setFontSize; flexible.rem2px = function (d) { var c = parseFloat(d) * this.rem; if ("string" == typeof d && d.match(/rem$/)) { c += "px"; } return c; }; flexible.px2rem = function (d) { var c = parseFloat(d) / this.rem; if ("string" == typeof d && d.match(/px$/)) { c += "rem"; } return c; } }(window, window.lib || (window.lib = {})); </script> </html>
擴展:
viewport
翻譯為中文可以叫做"視區"。手機瀏覽器是把頁面放在一個虛擬的"窗口"(viewport)中,通常這個虛擬的"窗口"(viewport)比屏幕寬,這樣就不用把每個網頁擠到很小的窗口中(這樣會破壞沒有針對手機瀏覽器優化的網頁的布局),用戶可以通過平移和縮放來看網頁的不同部分。
物理像素(physical pixel)
物理像素又被稱為設備像素,他是顯示設備中一個最微小的物理部件。每個像素可以根據操作系統設置自己的顏色和亮度。正是這些設備像素的微小距離欺騙了我們肉眼看到的圖像效果。
設備獨立像素(density-independent pixel)
設備獨立像素也稱為密度無關像素,可以認為是計算機坐標系統中的一個點,這個點代表一個可以由程序使用的虛擬像素(比如說CSS像素),然后由相關系統轉換為物理像素。
CSS像素
CSS像素是一個抽像的單位,主要使用在瀏覽器上,用來精確度量Web頁面上的內容。一般情況之下,CSS像素稱為與設備無關的像素(device-independent pixel),簡稱DIPs。
屏幕密度
屏幕密度是指一個設備表面上存在的像素數量,它通常以每英寸有多少像素來計算(PPI)。
設備像素比(device pixel ratio)
設備像素比簡稱為dpr,其定義了物理像素和設備獨立像素的對應關系。它的值可以按下面的公式計算得到:
設備像素比 = 物理像素 / 設備獨立像素
在JavaScript中,可以通過window.devicePixelRatio獲取到當前設備的dpr。而在CSS中,可以通過-webkit-device-pixel-ratio,-webkit-min-device-pixel-ratio和 -webkit-max-device-pixel-ratio進行媒體查詢,對不同dpr的設備,做一些樣式適配(這里只針對webkit內核的瀏覽器和webview)。
dip或dp,(device independent pixels,設備獨立像素)與屏幕密度有關。dip可以用來輔助區分視網膜設備還是非視網膜設備。
眾所周知,iPhone6的設備寬度和高度為375pt * 667pt,可以理解為設備的獨立像素;而其dpr為2,根據上面公式,我們可以很輕松得知其物理像素為750pt * 1334pt。
如下圖所示,某元素的CSS樣式:
width: 2px;
height: 2px;
在不同的屏幕上,CSS像素所呈現的物理尺寸是一致的,而不同的是CSS像素所對應的物理像素具數是不一致的。在普通屏幕下1個CSS像素對應1個物理像素,而在Retina屏幕下,1個CSS像素對應的卻是4個物理像素。
meta標簽
<meta>標簽有很多種,而這里要着重說的是viewport的meta標簽,其主要用來告訴瀏覽器如何規范的渲染Web頁面,而你則需要告訴它視窗有多大。在開發移動端頁面,我們需要設置meta標簽如下:
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
代碼以顯示網頁的屏幕寬度定義了視窗寬度。網頁的比例和最大比例被設置為100%。
CSS單位rem
rem就是相對於根元素<html>的font-size來做計算。而我們的方案中使用rem單位,是能輕易的根據<html>的font-size計算出元素的盒模型大小。而這個特色對我們來說是特別的有益處。