一、第一種方式是比較簡單的,開發速度也比較快。主要利用-webkit-transform:scale()這個屬性,比較設計稿和當前屏幕的寬度,或者高度,亦或者取兩者的最小值,來進行自適應。
1. 如果寬度自適應,如果兼容iphoneX的話,此時的設計稿的背景圖需要延長至1448,內容放在1206內,然后可以把背景圖設在一個寬高100%的容器內,background-size:100% auto,需要進行寬度自適應的內容統一放在一個容器內,居中,然后用js統一縮放這個容器,已達到自適應的效果;
2. 如果高度自適應,兼容iphoneX的設計稿需要調整成1218*936,內容放在629中間,進行高度自適應縮放。
3.還有一種就是取兩者的最小的那個來自適應。原理同上。
二、 比較簡單的頁面適配
比如頂部與底部的bar不管分辨率變化,高度和位置不變,中間的內容不管分辨率怎么變,都會位於左右兩邊等這種簡單的布局的開發原則是:
1、文字流式(使用文字隨着窗口變化自動換行)
2、控件彈性(flex布局)
3、圖片等比縮放等。
三、 網易的做法
動態計算html根元素的font-size,進而通過rem進行適配。
如果設計稿橫向分辨率是640px,為了計算方便,取100px的font-size為參照,那么body元素的寬度可以設置為6.4rem,於是html的font-size=deviceWidth / 6.4 ,這個deviceWidth就是viewport設置中的那個deviceWidth。這樣不同分辨率計算結果如下:
deviceWidth = 320,font-size = 320 / 6.4 = 50px deviceWidth = 375,font-size = 375 / 6.4 = 58.59375px deviceWidth = 414,font-size = 414 / 6.4 = 64.6875px deviceWidth = 500,font-size = 500 / 6.4 = 78.125px
同理,如果設計稿是750,則font-size=deviceWidth / 7.5,
deviceWidth = 320,font-size = 320 / 7.5 = 42.6667px deviceWidth = 375,font-size = 375 / 7.5 = 50px deviceWidth = 414,font-size = 414 / 7.5 = 55.2px deviceWidth = 500,font-size = 500 / 7.5 = 66.6667px
這樣的話,比如一個元素高度是210px,則height:2.1rem。
在dom ready后,需要通過以下代碼動態設置font-size:
document.documentElement.style.fontSize = document.documentElement.clientWidth / 6.4 + 'px';//設計稿640
document.documentElement.style.fontSize = document.documentElement.clientWidth / 7.5 + 'px'; //設計稿750
然后font-size可能需要額外的媒體查詢,並且font-size不能使用rem。比如:
@media screen and (max-width:321px){ .m-navlist{font-size:15px} } @media screen and (min-width:321px) and (max-width:400px){ .m-navlist{font-size:16px} } @media screen and (min-width:400px){ .m-navlist{font-size:18px} }
如果采用這種方式,視口要如下設置。
<meta name="viewport" content="initial-scale=1,maximum-scale=1, minimum-scale=1">
當deviceWidth大於設計稿的橫向分辨率時,html的font-size始終等於橫向分辨率/body元素寬。
之所以這么干,是因為當deviceWidth大於640時,則物理分辨率大於1280(這就看設備的devicePixelRatio這個值了),應該去訪問pc網站了。事實就是這樣,你從手機訪問網易,看到的是觸屏版的頁面,如果從pad訪問,看到的就是電腦版的頁面。如果你也想這么干,只要把總結中第三步的代碼稍微改一下就行了:
var deviceWidth = document.documentElement.clientWidth; if(deviceWidth > 640) deviceWidth = 640; document.documentElement.style.fontSize = deviceWidth / 6.4 + 'px';
var deviceWidth = document.documentElement.clientWidth; if(deviceWidth > 750) deviceWidth = 750; document.documentElement.style.fontSize = deviceWidth / 7.5 + 'px';
三、淘寶的做法
淘寶的做法和網易類似,也是使用了rem這個單位。通常采用如下viewport:
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
這樣整個網頁在設備內顯示時的頁面寬度就會等於設備邏輯像素大小,也就是device-width。這個device-width的計算公式為:
設備的物理分辨率/(devicePixelRatio * scale),在scale為1的情況下,device-width = 設備的物理分辨率/devicePixelRatio 。
devicePixelRatio稱為設備像素比,每款設備的devicePixelRatio都是已知,並且不變的,目前高清屏,普遍都是2,不過還有更高的,比如2.5, 3 等,我魅族note的手機的devicePixelRatio就是3。淘寶觸屏版布局的前提就是viewport的scale根據devicePixelRatio動態設置:
1、在devicePixelRatio為2的時候,scale為0.5
2、在devicePixelRatio為3的時候,scale為0.3333
這么做目的當然是為了保證頁面的大小與設計稿保持一致了,比如設計稿如果是750的橫向分辨率,那么實際頁面的device-width,以iphone6來說,也等於750,這樣的話設計稿上標注的尺寸只要除以某一個值就能夠轉換為rem了。通過js設置viewport的方法如下:
var scale = 1 / devicePixelRatio; document.querySelector('meta[name="viewport"]').setAttribute('content','initial-scale=' + scale + ', maximum-scale=' + scale + ', minimum-scale=' + scale + ', user-scalable=no')
淘寶布局的第二個要點,就是html元素的font-size的計算公式,font-size = deviceWidth / 10。
接下來要解決的問題是,元素的尺寸該如何計算,比如說設計稿上某一個元素的寬為150px,換算成rem應該怎么算呢?這個值等於設計稿標注尺寸/該設計稿對應的html的font-size。拿淘寶來說的,他們用的設計稿是750的,所以html的font-size就是75,如果某個元素時150px的寬,換算成rem就是150 / 75 = 2rem。
總結:
1、動態設置viewport的scale
var scale = 1 / devicePixelRatio; document.querySelector('meta[name="viewport"]').setAttribute('content','initial-scale=' + scale + ', maximum-scale=' + scale + ', minimum-scale=' + scale + ', user-scalable=no');
2、動態計算html的font-size
document.documentElement.style.fontSize = document.documentElement.clientWidth / 10 + 'px';
3、布局的時候,各元素的css尺寸=設計稿標注尺寸/設計稿橫向分辨率/10
4、font-size可能需要額外的媒介查詢,並且font-size不使用rem,這一點跟網易是一樣的。
5、跟網易一樣,淘寶也設置了一個臨界點,當設備豎着時橫向物理分辨率大於1080時,html的font-size就不會變化了,原因也是一樣的,分辨率已經可以去訪問電腦版頁面了。
淘寶開源的解決方案:https://github.com/amfe/lib-flexible
代碼如下:
(function flexible (window, document) { var docEl = document.documentElement var dpr = window.devicePixelRatio || 1 // adjust body font size function setBodyFontSize () { if (document.body) { document.body.style.fontSize = (12 * dpr) + 'px' } else { document.addEventListener('DOMContentLoaded', setBodyFontSize) } } setBodyFontSize(); // set 1rem = viewWidth / 10 function setRemUnit () { var rem = docEl.clientWidth / 10 docEl.style.fontSize = rem + 'px' } setRemUnit() // reset rem unit on page resize window.addEventListener('resize', setRemUnit) window.addEventListener('pageshow', function (e) { if (e.persisted) { setRemUnit() } }) // detect 0.5px supports if (dpr >= 2) { var fakeBody = document.createElement('body') var testElement = document.createElement('div') testElement.style.border = '.5px solid transparent' fakeBody.appendChild(testElement) docEl.appendChild(fakeBody) if (testElement.offsetHeight === 1) { docEl.classList.add('hairlines') } docEl.removeChild(fakeBody) } }(window, document))
開發步驟:
第一步,視覺設計階段,設計師按寬度750px(iPhone 6)做設計稿,除圖片外所有設計元素用矢量路徑來做。設計定稿后在750px的設計稿上做標注,輸出標注圖。同時等比放大1.5倍生成寬度1125px的設計稿,在1125px的稿子里切圖。
第二步,輸出兩個交付物給開發工程師:一個是程序用到的@3x切圖資源,另一個是寬度750px的設計標注圖。
第三步,開發工程師拿到750px標注圖和@3x切圖資源,完成iPhone 6(375pt)的界面開發。此階段不能用固定寬度的方式開發界面,得用自動布局(auto layout),方便后續適配到其它尺寸。
第四步,適配調試階段,基於iPhone 6的界面效果,分別向上向下調試iPhone 6 plus(414pt)和iPhone 5S及以下(320pt)的界面效果。由此完成大中小三屏適配。
注意第三步,就要使用我們以上介紹的網易跟淘寶的適配方法了。假如公司設計稿不是基於750的怎么辦,其實很簡單,按上圖做一些相應替換即可,但是流程和方法還是一樣的。解釋一下為什么要在@3x的圖里切,這是因為現在市面上也有不少像魅藍note這種超高清屏幕,devicePixelRatio已經達到3了,這個切圖保證在所有設備都清晰顯示。
