摘要:說到響應式布局方案,我們首先需要了解視口這個概念視口在早期的時候我們沒有專門針對手機尺寸寫的頁面,所以在用手機瀏覽頁面的時候我們看到的都是專門針對端的頁面,在這種情況下頁面會被嚴重壓縮,而且會極大的影響頁面的結構和布局,為了解決這個問題,蘋
說到響應式布局方案,我們首先需要了解視口這個概念
視口在早期的時候我們沒有專門針對手機尺寸寫的頁面,所以在用手機瀏覽頁面的時候我們看到的都是專門針對PC端的頁面,在這種情況下頁面會被嚴重壓縮,而且會極大的影響頁面的結構和布局,為了解決這個 問題,蘋果公司提出了視口的概念,因為我們早期的PC端的頁面的版心一般是960px,為了容納這個頁面,我們在手機建立一個虛擬的區域,大小一般為980px,來容納PC的頁面,以方便用戶來瀏覽頁面
但是在如今移動端快速發展的時候,我們有了專門針對手機屏幕尺寸的的移動端頁面,所以在寫移動端的頁面的時候我們需要調整視口的寬度,保證頁面內容會在手機屏幕尺寸大小的頁面上進行展示
媒體查詢 媒體類型
媒體查詢可以為不同的設備規定不同的樣式,常用的一般有三種設備 screen(計算機屏幕,該值是默認值)、print(打印預覽)、all(所有設備)
@media screen媒體屬性
媒體屬性用來規定在指定的符合某些條件的情況下為指定的元素設置樣式,需要注意媒體屬性必須用()包起來,否則無效,常用的媒體屬性有
width 可視區域寬度,取值格式為指定寬度或者范圍,如 @media (width: 900px){ }
height 可視區域高度,取值格式為指定寬度或者范圍,如 @media (max-height: 900px){ }
device-width 設備寬度,取值格式為指定寬度或者范圍,如 @media (max-device-width: 5000px) { }
device-height 設備高度 取值格式為指定寬度或者范圍,如 @media (max-device-height: 5000px) { }
orientation 設備是豎屏還是橫屏模式,可選值有landscape(橫屏)、portrait(豎屏),如 @media (orientation: landscape) { }
aspect-ratio 可視區域寬高比,取值格式為水平像素/垂直像素,如@media (device-aspect-ratio:16/9) { }
device-aspect-ratio 設備寬高比,取值格式為水平像素/垂直像素,如@media (device-aspect-ratio:16/9) { }
例如我們要針對某個設備的body在橫屏時設置的背景顏色是黑色,在豎屏的時候背景是白色,那么可以使用以下寫法
html, body { height: 100%; } @media (orientation: landscape) { body{ background-color:#000; } } @media (orientation: portrait) { body{ background-color:#fff; } }邏輯操作符
媒體查詢可以使用三種操作符,通過操作符配合媒體屬性來判斷是否載入媒體屬性下的樣式表
and 將每一個條件組合起來,只有當所有條件都成立時條件才成立,可以理解為JavaScript中的&
not 對媒體查詢的條件取反
or 只要有一個媒體屬性條件成立就成立,可以理解為JavaScript中的||
配合邏輯操作符設置設備在可視窗口大小變化時背景顏色發生改變
html,body{ height: 100%; } @media screen and (max-width: 500px ){ body{ background-color: skyblue; } } @media screen and (min-width: 501px) and (max-width: 800px){ body{ background-color: #ccc; } } @media screen and (min-width: 900px){ body{ background-color: yellowgreen; } }vw、vh布局方案
在CSS3規范中引入了vw、vh單位,分別將視口劃分為100份,一個vw單位相當于視口寬度的1%,一個vh相當于視口高度的1%,需要注意的是不同于百分比的布局方案,vw和vh不受父元素寬高的影響,只由視口的大小決定
同時還有兩個單位vmax、vmin,vmax表示取視口寬度和高度中比較大的值,將其等分為100份,vmin表示取比較小的值,將其等分為100份
vw、vh
目前瀏覽器的支持情況
rem布局rem是css中的一個單位,是根據根字體大小來設定的,也就是html的font-size
在正常的UI設計稿件的時候一般設置大小為640/750px大小,我們一般選擇將稿件等分為20份(20份在設備大小和稿件大小一般可以除盡,我們盡量避免出現小數)
那么如果UI稿件為640px大小,每一份的大小為32px,假設UI稿件上有一個160*160大小的元素,那么該元素占整個頁面的160/32份
同時我們也將屏幕分為20份,以Iphon為例(屏幕大小為320px),那么每份大小為16px,我們通過媒體查詢將html根字體大小設置為16px,那么在UI稿件上160px大小的元素在Iphon5上的實際大小為160/32 rem,那么通過這個公式我們就可以通過JavaScript設置不同的根節點字體大小來進行適配
我們來寫一個簡單的例子
(function (doc, win) { var docEl = doc.documentElement, /* document.documentElement 返回文檔的根節點 * orientationchange 在用戶移動端設備屏幕垂直或水平旋轉移動設備時被觸發 * resize 事件,在綁定元素大小發生變化時觸發該事件,例如檢測屏幕變化: * window.addEventLisenter("resize",function(){ * alert("屏幕大小變化了") * }) * * resize 屬性,css3新增屬性,用來指定用戶是否可以縮放該元素 * none:用戶無法調整該元素尺寸 * both:用戶可以調整元素的高度和寬度 * horizontal:用戶可調整元素的寬度 * vertical:用戶可調整元素的寬度 * */ resizeEvt = "orientationchange" in window ? "orientationchange" : "resize", recalc = function () { var clientWidth = docEl.clientWidth; if (clientWidth >= 640) { clientWidth = 640 } if (!clientWidth) return; docEl.body.style.fontSize = (clientWidth / 640) * 100 + "px"; }; win.addEventListener("resizeEvt", recalc, false); /* * DOMContentLoaded 該事件會在load事件之前觸發,在DOM樹構建完成時就觸發 * 而load事件則是在DOMContentLoaded事件觸發之后,繼續加載圖片等外部文件完成后觸發 * */ doc.addEventListener("DOMContentLoaded", recalc, false) })(document, window)
之前一直在使用手淘的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 = {}); if (metaEl) { 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)); } } } //如果用戶自定了name="viewport"的meat標簽,那么通過match獲取用戶設置的initial-scale,也就是縮放級別,然后獲得設置dpr //如果用戶沒有設定name="viewport"的meat標簽,那么獲取flexible.js自身定義的縮放級別來設置dpr if (!dpr && !scale) { //檢測的當前設備的版本 var isAndroid = win.navigator.appVersion.match(/android/gi); var isIPhone = win.navigator.appVersion.match(/iphone/gi); var devicePixelRatio = win.devicePixelRatio; //window.devicePixelRatio 該屬性返回當前顯示設備的物理像素分辨率與css像素分辨率的比值 //可以通過重寫window.devicePixelRatio來更改此屬性,例如window.devicePixelRatio=2; 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; } docEl.setAttribute("data-dpr", dpr); //判斷頁面是否存在 metaEl 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); } } function refreshRem(){ var width = docEl.getBoundingClientRect().width; //getBoundingClientRect //返回一個DOMRect對象,包含一組矩形的集合,該集合內是與該元素相關的css邊框集合 // DOMRect // bottom:8 // height:8 // left:0 // right:520 // top:0 // width:520 // x:0 // y:0 if (width / dpr > 540) { width = 540 * dpr; } //手淘的布局方案默認將屏幕分成十份,當然,如果愿意我們可以對其進行更改 var rem = width / 10; docEl.style.fontSize = rem + "px"; flexible.rem = win.rem = rem; } // resize 在設備寬度發生改變時觸發 win.addEventListener("resize", function() { clearTimeout(tid); tid = setTimeout(refreshRem, 300); }, false); //pageshow firefox/open的一個事件,在chrome中不會觸發 //在頁面后退時靜態資源會直接重緩存中讀取 win.addEventListener("pageshow", function(e) { if (e.persisted) { clearTimeout(tid); tid = setTimeout(refreshRem, 300); } }, false); //document.readyState 描述文檔的加載狀態 // loding 文檔仍然在加載中 // interactive 文檔已經加載完成并已經被解析,但是圖像,框架之類的資源仍然在加載中 // complete 說有資源都已經加載完成,load事件即將被觸發 // 在狀態改變時document.readyState事件將被觸發 if (doc.readyState === "complete") { doc.body.style.fontSize = 12 * dpr + "px"; } else { //DOMContentLoaded 在文檔加載完成后觸發,不會等待圖像,框架等資源,參考$(function(){}) / $.ready() doc.addEventListener("DOMContentLoaded", function(e) { doc.body.style.fontSize = 12 * dpr + "px"; }, false); } refreshRem(); flexible.dpr = win.dpr = dpr; flexible.refreshRem = refreshRem; //rem 2 px 轉化方法 flexible.rem2px = function(d) { var val = parseFloat(d) * this.rem; if (typeof d === "string" && d.match(/rem$/)) { val += "px"; } return val; } //px 2 rem 轉化方法 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"] = {}));
手淘的布局方法主要是通過dpr來設置不同屏幕下的不同比例關系,drp指的是默認縮放為100%的情況下設備像素和CSS像素的比值
dpr=設備像素 / CSS像素
具體的關于dpr的解釋可以看下面這篇文章
移動web開發之像素和DPR
如果使用手淘的布局方案注意一個問題,我們需要去除頁面中設置了name=viewport的meta標簽,在源碼中我們可以看到如果存在改標簽,那么lib-flexible不會動態改變縮放比例
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/101746.html
摘要:優點在于響應式布局非常方便,都是按照比例進行的縮放,弊端是在于如果圖片不規則,那么圖片變形是難免的。一次布局多終端友好 技術開發和實際運營總是有很大差別的,比如常見的圖片列表,一般設計圖上都是固定尺寸大小的,但是實際操作起來并沒有太多人去ps修剪圖片到知道的尺寸,大部分都是差不多比例的圖片就直接上傳了,為了解決不規則圖片列表展示問題有相應的解決方案例如瀑布流,或者相冊等,但是對于多終端...
摘要:優點在于響應式布局非常方便,都是按照比例進行的縮放,弊端是在于如果圖片不規則,那么圖片變形是難免的。一次布局多終端友好 技術開發和實際運營總是有很大差別的,比如常見的圖片列表,一般設計圖上都是固定尺寸大小的,但是實際操作起來并沒有太多人去ps修剪圖片到知道的尺寸,大部分都是差不多比例的圖片就直接上傳了,為了解決不規則圖片列表展示問題有相應的解決方案例如瀑布流,或者相冊等,但是對于多終端...
摘要:做移動端自適應時可能很多人都對自適應和之間的關系產生疑問也有一些人會疑慮比如我的自適應方案沒有加會不會出問題針對這些疑問我說一下我的見解。 做移動端自適應時可能很多人都對自適應和dpr之間的關系產生疑問,也有一些人會疑慮比如我的自適應方案沒有加dpr會不會出問題,針對這些疑問我說一下我的見解。 1. 什么是尺寸自適應 首先標題說的自適應,可能自適應在不同人眼里理解不同,特別與響應式的關...
閱讀 2781·2023-04-25 14:41
閱讀 2375·2021-11-23 09:51
閱讀 3674·2021-11-17 17:08
閱讀 1667·2021-10-18 13:31
閱讀 5528·2021-09-22 15:27
閱讀 910·2019-08-30 15:54
閱讀 2222·2019-08-30 13:16
閱讀 728·2019-08-29 17:04