完整目錄:javascript
基本概念
物理像素
設備獨立像素
CSS 像素
PPI的概念
DPR的概念
縮放的概念
viewPort 的概念
viewport 渲染流程
Meta 標籤說明css
移動端佈局實踐
混合方式
REM 方式
響應式
JS自動換算
縮放方式
CSS3 縮放
viewport 縮放html
相關補充
爲何須要meta標籤?
傳統響應式佈局與移動端響應式的區別
移動端字體以及大小的設置
移動端背景圖縮放設置
使用Sass提升px與rem轉換效率
經過Chrome進行真機調試
weinre 遠程調試前端
混合方式實現的移動端佈局實際上就是對PC端佈局技術的組合使用,它主要包含如下技術:java
將這些佈局方法根據頁面每一個不一樣部分的特性進行組合使用,例如模態框,彈出層等能夠採用定位方式,而頁面元素的排版能夠採用浮動佈局,也可使用具備可塑性的Flex佈局方案,對於元素的尺寸能夠採用百分比或者其它相對單位,而這即是我稱之爲「混合方式」的緣由。
混合方式進行的移動端網頁佈局,所採用的技術一般都具備靈活、可伸縮、可塑等特色,甚至連使用的單位,最好都是相對單位,也只有這樣才能知足屏幕尺寸多樣性的移動設備。android
對於混合佈局技術,我首先要說幾點我認爲比較重要的基礎知識點:ios
· 聲明meta標籤
經過meta標籤來聲明viewport是進行手機端頁面開發的必須也是起始步驟css3
<meta name="viewport" content="width=device-width,maximum-scale=1,minimum-scale=1,user-scalable=no />
· 百分比計算公式
若是你在進行移動端網頁佈局中使用到了百分比單位,那麼這個公式你必定要清楚web
百分比 = 目標尺寸 / 上下文尺寸。
其中目標尺寸就是當前元素的尺寸,而上下文尺寸則是包含當前元素的父元素,經過 目標尺寸 / 上下文尺寸
即可以獲得咱們須要的百分比結果,另外我的建議百分比結果保留全部小數。chrome
· 設置閥值
可伸縮的佈局方案有一個本質特色就是會根絕顯示設備的尺寸進行自適應調整,這一特性自己就是咱們所期待的,可是在某些極端的環境下,好比過大或太小的屏幕下,某些元素尺寸也會變的過大或者太小,或者圖片被嚴重拉伸,致使失真等,從而使顯示效果變的不好,而下面的這些CSS屬性就能夠很簡單解決這些問題。
max-width: //設置最大寬度閾值 min-width: //設置最小寬度閾值 max-height //設置最大高度閾值 min-height //設置最小高度閾值
在使用上能夠將它們做用在目標元素上,或者對目標元素有所限制的上級元素。
· 對於單位的認識
對於網頁佈局的單位,咱們不只要知道px就夠了,還要知道其它幾個比較經常使用的單位,特別是CSS3推出的一些新的度量單位。
em
em 是一種相對單位,它相對於父元素的字體大小。
em 經常使用於可縮放的字體需求中,好比在一個多行段落文本中,若是咱們設置行高爲 line-height:16px
這一固定的像素值,那麼一旦在縮放或者改變了文字的大小的狀況下,字體會發生大小變化,可是行高的值卻不會發生改變,永遠爲16px,若是咱們設置行高爲 line-height:1em
那麼此時行高的值即是一種相對的狀況,它會隨着文字大小的改變而改變。
由於em是相對於父元素的字體大小,因此在使用上咱們一般都是爲 body
設置字體大小,這樣即可以實現一改全改的效果。另外咱們還須要瞭解的是,瀏覽器默認的字體大小是16px,所以 1em 也就等於 16px。
rem
rem是一種相對單位,它相對於根元素 html
的字體大小。
利用這一特性,rem經常使用於移動端頁面佈局,下文中咱們會更詳細的說到。
vh/vw
vh/vw都是相對於視口的單位,瀏覽器視口的區域就是經過 window.innerWidth
以及 window.innerHeigth
度量獲得的範圍。
瀏覽器會將整個視口的寬度或者高度劃分爲100等份,所以1vw或者1wh就是相對視口寬度或者高度的1%。例如瀏覽器視口的寬度是1920,那麼 1920/100 每等份即19.2px。
vh/vw 在使用上很相似與百分比,可是vh/vw也具備百分比不具備的特性,那就是相對於視口,例如當父級元素不具備尺寸的時候,百分比便沒法產生做用,可是相對於視口的vh/vw則能夠。
vh/vw 還能夠應用在一個頁面上有不少垂直排列的區塊,並且每一個區塊的高度都是當前瀏覽器顯示區域高度的狀況下。
vmin / vmax
vmin / vmax 也是相對於視口的單位,可是vmin會根據視口寬高最小的那個爲基準,而後分爲100等份,而vmax 則會以視口寬高最大的那個一個爲基準,而後分爲100等份。
在瞭解了以上的基本知識後,我會根據一個現成的示例去解讀混合方式的使用實例,這裏我就以手機新浪網爲例。
首先打開手機新浪網:https://sina.cn/
,在chrome下按 F12
,從上至下觀察,咱們能夠看到,新浪手機版頁面的head中,經過meta標籤對viewport的尺寸以及縮放進行了調整,再大體的看下頁面內容咱們能夠看出手機新浪網上很好的運用了H5新增的語義化標籤,例如:
section : 定義每一個區域 details : 設置display:none隱藏,來表述對區域內容或做用的聲明 mark : 標記內容,好比廣告等。 nav : 用做導航 aside : 用於表示與頁面主內容鬆散相關的內容,常常用於側邊欄、廣告、友情連接、引文以及導航元素等。 header : 定義頭部區域 footer : 定義了網頁的尾部,它主要包含聯繫方式、地址、備案信息等。
再從總體到細節,首先是banner區域,咱們會發現banner區域的HTML結構很簡單,就是 div > a > img + mark
結構,並且img的寬度是100%即當前顯示區域的100%,高度則是自動適應。
接着,咱們看手機版的頭部,它位於banner的下面,主要由logo、兩個按鈕以及經常使用功能按鈕(天氣,登陸)等組成,整個佈局的思路是左右結構,logo與兩個切換按鈕都是左浮動,而經常使用功能按鈕則是採用右浮動。這樣的好處就體現於在左右兩個結構之間留下了足夠多的空白區域。
再接着的即是導航區域,導航的按鈕數量不少,可是結構依然很簡單,就是 nav > a
結構,而且全部的 a
進行左浮動,由於 a
中的內容都是文字,因此每一個導航按鈕的高度能夠經過 line-height
進行控制,每一個按鈕之間的間隔則用 padding
撐開,寬度則是根據一行要展現的按鈕數量除以1,這裏一行顯示6個再考慮到間距,所以寬度都是15%,採用百分比單位,最後經過 white-space:nowrap
強制控制按鈕內容不換行。
再往下即是焦點圖區域,這個區域跟咱們日常編寫焦點圖基本類似,因此就不在贅述。
最後即是頁面主要的資訊內容區域,經過控制檯咱們能夠獲得內容區域的主要結構是 dl > dt + dd
而且 dl 應用了 display:flex
,因此dl中的dt與dd便會水平並排自動劃分寬度排列。dt中的是新聞圖片,而dd中則存放新聞標題以及icon,並且dd也應用了box特性,並經過如下CSS屬性,設置其內容及子元素的水平以及垂直排列方式
-webkit-box-orient:vertical; // 設置內容或子元素爲上下垂直排列 -webkit-box-pack:justify // 設置內容或子元素爲兩端排列
總的來講,混合模式在使用上其優勢在於技術上接近傳統PC端頁面的佈局方式,而你所要作的只是對PC上的佈局技術進行稍微的改變,可是其缺點也很明顯那就是關鍵元素高寬和位置都不變,只有容器元素在作伸縮變換,因此對於混合模式下的佈局,元素、圖片、文字在設計的時候都 要知足如下特性:
·彈性的元素控件 ·自適應的圖片尺寸 ·流式的文字展現
更直觀的理解,能夠看下圖:
REM 是一種相對單位,它依據的是「根」節點的字體 (font-size) 的大小。
REM 是目前移動端頁面佈局經常使用的方式,它可使整個頁面的全部元素都隨着顯示設備尺寸的變化而相應的調整本身的尺寸,從而加強頁面對設備適配的靈活性,這種變化我稱之爲「頁面的縮放」。
既然REM會讓頁面根據不一樣的顯示設備進行適配縮放,那麼必然就會有一個 標準頁面尺寸,就目前而言,整個前端開發界使用最多的標準頁面尺寸則是根據iphone4或者 iPhone5爲依據的 640px*1366px
,也有以iphone6爲基準的750px。這個標準的頁面尺寸,咱們能夠將其定義爲1,若是當前的顯示設備尺寸小於標準頁面尺寸(640px或者750px)那麼便讓頁面尺寸縮小,使其小於1。而當顯示設備尺寸大於標準頁面尺寸,咱們便可以作一些其它的適配,也能夠將頁面整個居中顯示在顯示設備中而後不進行任何縮放操做。
經過上述,咱們能夠知道兩個關鍵點,一是頁面的縮放,這個咱們等下會說到,二就是採用rem爲單位進行頁面佈局,實際上rem佈局與px佈局並無什麼本質的區別,這個咱們能夠代入實例去理解,好比如今 html
的 font-size
的大小是100px,即 1rem = 100px,若是如今頁面中要放入一個200*200的盒子,那麼按照等比關係,即:
div{ width:2rem; height:2rem; background:gray; }
除了將rem與px結合起來進行理解rem佈局的原理,淘寶的前端工程師也提出了另外一種理解方式,這種方式的優勢在於能夠向後與 vw/vh 進行兼容理解,首先將頁面劃分爲100分,每一份的寬度爲(n)px,設定1rem = 10n,若是基準頁面是640px的話,那麼每份即6.4px 而 1rem = 64px。若是如今有一個 200px * 200px 的盒子,那麼按照rem與px的等比關係,即:
div{ width:3.125rem; height:3.125rem; background:gray; }
最後咱們談談 REM 實現的頁面縮放適配原理, rem 是依據 html
標記的 font-size
大小的相對單位,對於使用rem爲單位的頁面,在被載入到顯示設備顯示的時候,會根據顯示設備的尺寸,而後對應的修改html標籤的font-size值,這樣即可以一處修改,整個頁面內容都會發生改變,即實現根據設備尺寸進行縮放的效果。
REM方式進行移動端佈局的原理都是相同的,可是不一樣的在與對於設備尺寸的檢測上,就目前而言分爲兩種,一種是經過CSS meida查詢,另外一種則是經過JS檢測。
響應式方式就是經過 CSS media 對顯示設備進行媒體查詢來改變rem與px的對應關係。
下面我貼出我己工做中使用到的移動端媒體查詢規則:
@media screen and (min-width:320px) and (max-width:359px) { html { font-size: 50px; } } @media screen and (min-width:360px) and (max-width:374px) { html { font-size: 56.25px; } } @media screen and (min-width:375px) and (max-width:383px) { html { font-size: 58.59375px; } } @media screen and (min-width:384px) and (max-width:399px) { html { font-size: 60px; } } @media screen and (min-width:400px) and (max-width:413px) { html { font-size: 62.5px; } } @media screen and (min-width:414px) and (max-width:431px) { html { font-size: 64.6875px; } } @media screen and (min-width:432px) and (max-width:479px) { html { font-size: 67.5px; } } @media screen and (min-width:480px) and (max-width:539px) { html { font-size: 75px; } } @media screen and (min-width:540px) and (max-width:639px) { html { font-size: 84.375px; } } @media screen and (min-width:640px) { html { font-size: 100px; } body { max-width: 640px !important; margin: 0px auto !important; } }
在上面這段CSS媒體查詢代碼中,咱們以一個640px寬度的設計稿爲基準的頁面尺寸,並設定 html
標記的 font-size
值爲100px,而後檢測載入當前頁面的顯示設備尺寸,對應的改變font-size的值,最後再進行相應的縮放適配顯示頁面,當顯示設備尺寸大於基準頁面尺寸時則居中顯示在顯示設備中。
響應式REM佈局的優勢在於能夠根據設計稿的特色,自定義的對某些設備進行單獨適配,而缺點是檢測規則固定不可變,這一點相比於「JS自動換算」更爲明顯。
根絕響應式方式的REM思路,咱們就能夠很簡單的經過JS代碼寫出相應的JS換算方式。
代碼以下:
(function(win,doc){ var timer = null, html = doc.documentElement, baseWidth = html.dataset.basewidth*1 || 640, metaEl = document.querySelector('meta[name="viewport"]'), event = 'onorientationchange' in win ? 'onorientationchange' : 'resize'; if(!metaEl){ metaEl = document.createElement('meta'); metaEl.setAttribute('name','viewport'); metaEl.setAttribute('content','initial-scale=1,maximum-scale=1,minimum-scale=1,user-scalable=0'); html.firstElementChild.appendChild(metaEl); } function layoutCalc(){ var width = html.getBoundingClientRect().width, ratio = width / baseWidth * 100, devicePixelRatio = window.devicePixelRatio, rem = ratio < 100 ? ratio < 50 ? 50 : ratio : 100; if(!/\.\d+/.test(devicePixelRatio.toString())){ html.dataset.dpr = devicePixelRatio; } html.style.fontSize = rem + 'px'; } win.addEventListener(event,function(){ clearTimeout(timer); timer = setTimeout(layoutCalc,300); },false); win.addEventListener('pageShow',function(e){ if(e.persisted){ clearTimeout(timer); timer = setTimeout(layoutCalc,300); } },false); layoutCalc(); }(window,document));
功能說明:
· 自定義基準頁面尺寸
經過爲 html 標籤添加 data-basewidth
屬性來自定義指定基準頁面的尺寸。
示例:
<html data-basewidth="750" > </html>
· 定義頁面內容的字體大小
對於一些符合標準的dpr值(只要是整數,例如:1,2,3),都會爲 html
標籤再附加一個 data-dpr
屬性,而後開發者即可以根據這個屬性爲條件,實如今不一樣dpr狀況下,對內容字體的大小的調整。
示例代碼:
html[data-dpr="1"] .dpr-text{ font-size:12px; } html[data-dpr="2"] .dpr-text{ font-size:24px; } html[data-dpr="3"] .dpr-text{ font-size:36px; }
<p class="dpr-text">測試文字</p>
相比「響應式方式」JS自動換算無需添加規則,適合於各種型的顯示設備。
一樣是「縮放」 REM方式在縮放的時候,會改變元素的尺寸,而下面要提到的縮放方式,並不會改變元素的原有尺寸,能夠理解成只是在視覺上將內容或者頁面縮放至與當前顯示設備相匹配的尺寸。
這種縮放方式,也能夠分爲兩種類型:
· 經過CSS3的transform對元素進行縮放。 · 對viewport進行縮放。
首先貼出具體的代碼(我已經作好註釋):
function pageScale(opt) { var ua = navigator.userAgent, wp = ua.match(/Windows Phone ([\d.]+)/), android = ua.match(/(Android);?[\s\/]+([\d.]+)?/), dom = document.querySelectorAll(opt.selector), // 獲取要縮放的DOM,能夠多個。 dw = document.documentElement.clientWidth, // 獲取當前顯示設備的寬度 dh = document.documentElement.clientHeight, // 獲取當前顯示設備的高度 pw = opt.width || 320, //獲取設計稿的最小尺寸 - 寬度 ph = opt.height || 568, // 獲取設計稿的最小尺寸 - 高度 mode = opt.mode || 'cover', // 獲取顯示模式 origin = opt.origin || 'left top 0', // 設置縮放中心點 ratio = 0, // 定義比值 i = dom.length; // 獲取要調整DOM的個數 // 根據模式的不一樣,從而生成響應的比值,總的來講contain模式只關注寬高中最小的那個。 if (mode == "contain") { if (pw > ph) { ratio = dw / pw; } else { ratio = dh / ph; } } else if (mode == "cover") { // cover模式下,只關注寬高最大的那個。 if (pw < ph) { ratio = dw / pw; } else { ratio = dh / ph; } } else { ratio = dw / pw; } function calcScale(_mode, obj, num) { var _o = obj.style; _o.width = pw + "px"; _o.height = ph + "px"; _o.webkitTransformOrigin = origin; _o.transformOrigin = origin; _o.webkitTransform = "scale(" + num + ")"; _o.transform = "scale(" + num + ")"; // 兼容android 2.3.5系統下body高度不自動刷新的bug if (_mode == "auto" && android) { document.body.style.height = ph * num + "px"; } else if (_mode == "contain" || _mode