今天週日,我正坐在黃埔區圖書館,思索着關於移動端屏幕適配的問題。做爲一名年紀輕輕的前端馬蓉,不,是碼農,移動端屏幕適配的方案的帖子沒讀過100篇吧,也讀過幾十篇了。但是今天我又在思考這個問題了,由於下週我有個關於移動端適配的演講。人生這麼短暫,我卻把有限的時間奉獻到了無限的前端道路上。javascript
根據我不(cong)太(ming)靈(jue)活(ding)的大腦的努力思考。我發現現階段比較流行移動端適配原理只有一個——就是對元素進行放大和縮小,具體到執行的時候方法有兩個(求不打臉)。 1個是網頁大小不變只對其中的元素進行放大縮小的rem單位值縮放法,另1種是對直接對整個網頁進行放大縮小的網頁縮放法。爲何你沒有聽過這兩個方法?由於這兩個方法的名字都是我起的,還沒著名起來。css
rem單位值縮放法;具體作法是讓1rem對應的px值根據手機的不一樣而不一樣,可能在iphne5上1rem等於10px,在iphone6上1rem就等於11.7px了(iphone6的屏幕寬度是iPhone5屏幕寬度的1.17倍,因此1rem對應的px值也要是1.17倍)。 具體1rem值是多少,能夠經過js或者css3的媒體查詢算出來。而後網頁上的元素都使用rem做爲尺寸單位。iphone5上表現良好的頁面,放到iphone6上的時候,由於rem對應的px值被放大了,因此全部元素的尺寸位置也被等比例放大了,因此在iphone6下天然也就表現良好了。修改rem值的方法有兩個。html
1.1 使用js修改html的fontsize值大小。前端
1.2 使用媒體查詢修改html的fontsize值大小。java
網頁縮放法:這個方法就簡單暴力了,搞得人內心常常怕怕的。具體作法就是以一個手機爲基準,通常是iphone5。在iphone5上先製做好頁面,製做完頁面以後再在頁面加入一段適配的js,這段js的做用就是獲取屏幕的寬度而後與iphone5進行比較,比iphone5寬的就把網頁放大,比iphone5頁面窄的就把網頁縮小。好比iPhone6的手機屏幕寬度是iphone5的1.17倍,就經過js把整個網頁放大1.17倍。醬紫在iphone5上表現良好的頁面在iphone6上就沒問題了。具體怎麼放大縮小,有兩種方法。css3
2.1 縮放html元素,使用transfrom的scale屬性或者zoom屬性。web
2.1 使用meta標籤的 initial-scale、minimum-scale和maximum屬性chrome
看到這裏,你可能有個疑問,爲啥咱們都是根據寬度去調整頁面而不是根據高度啊。根據我抄襲別人的經驗,高度調整是比較容易的,給底部的元素一個bottom定位就能夠。不行你就往中間擠擠嘍,我說的方法只是講原理,你要是想作的完美還要靈活運用canvas
若是你看完序言的一、2點,恭喜你,你已經掌握掌握了移動端適配的九陽神功了。下面就是打通任督二脈的時候,骨骼驚奇的人能夠飄過。瀏覽器
ps:這名字是我起的。
w3c定義:font size of the root element
翻譯一下:rem爲根元素的字體大小。網頁的根元素就是html元素,因此rem就是html元素的字體大小。
假設html字體大小16px,那麼1rem就是16px。假設html字體大小爲10px,那麼1rem就是10px。
移動端的設計稿通常都是以iphone5爲準設計的,爲了顯示清晰,設計稿的尺寸一般是屏幕尺寸的兩倍。好比iphone5的尺寸是320x568,因此設計稿通常640x1136。根據狀況的不一樣,設計稿也有640x1008和640x960的。高度比較容易調整,寬度能保證是兩倍就能夠啦。
由於設計稿是以iphone5爲準設計的,因此咱們製做的時候最好也是以iphone5爲準,這樣比較好計算。其餘屏幕只要咱們頁面進行放大和縮小就能達到適配的效果。
由於咱們是採用rem單位值縮放法,因此首先要確認一點,1rem值要等於多少px比較合適。其實這裏就比較隨意了,你愛設置成多少就能夠設置成多少。固然從實際應用的角度出發,把rem值設置成10px或者100px會比較好,由於計算方便。咱們這裏以1rem等於10px爲例
此時咱們須要在頁面添加以下css
html{ font-size:10px; }
由於全部的瀏覽器默認字體大小都是16px,因此咱們也能夠設置html的fontsize爲62.5% (10/16*100%);
html{ font-size:62.5%; }
ps,默認狀況下瀏覽器容許的最小字體是12px,即便你把字體設置成10px,瀏覽器仍是按照12px來顯示。爲了解決這個問題,須要你在html上設置一個樣式;
html{ text-size-adjust:none; -webkit-text-size-adjust:none; }
由於1rem=10px。因此把px轉化爲rem的時候,只要把px的值除以10再把單位由px轉爲rem就能夠了。對應到設計稿上的話,由於設計稿尺寸是屏幕尺寸的2倍,因此把設計稿上的元素尺寸由px轉化爲rem的時候是除以20(先把設計稿縮小2倍,使設計稿跟屏幕尺寸同樣大,再除以rem和px10倍的對應關係)。假設設計稿上有個圖片寬高是100px,對應的rem值就是5rem(100/2/10)。
其實這一點不用講了,1rem就是10px。可是避免1.2.3有誤導,因此特別說明下。
假設你是在chrome開發者工具上,設置個元素的寬高爲100px。那麼轉化成對應的rem就是10rem(100/10)而非5rem(100/2/10)。由於此100px相對的是320px的屏幕而非640的設計稿,因此不用再除以2了。
通過前面的4點,你的設計稿在iPhone5上應該已經能正常顯示了。此時你用iphone6看的話,你的頁面可能錯亂了。由於你尚未在iphone6對頁面作適配,也就是你在iPhone6下尚未修改rem對應的px值的大小。
這個方法比較簡單,獲取其餘手機屏幕相對於iphone5手機屏幕的大小,而後放大和縮小html的fontsize值就能夠了。這個方法有個缺點就是fontsize值可能爲小數,有可能致使頁面上的文字出現模糊不清的狀況。只要微調下就能夠並非大的問題。js代碼以下:
(function(){ var scale = window.innerWidth/320; document.documentElement.style.fontSize = 10*scale+"px"; })()
使用上面這段代碼是有前提的,就是頁面必需要加這段html代碼。
<meta name="viewport" content="width=device-width,minimum-scale=1,maximum-scale=1">
在移動端的發展過程當中,早期的手機爲了正常顯示pc頁面,手機默認的viewport的寬度並非手機屏幕的寬度,通常默認的viewport寬度爲980px,固然也有手機默認的寬度爲1280px。這樣若是你不把viewport的寬度設置爲device-width的話,window.innerWidth就是默認值980px或者是1280px。這樣咱們上一段代碼就有問題了。咱們使用window.innerWidth獲取的並非屏幕的寬度,因此求出來的scale也就錯了。
解決方法有兩個,一個是加上meta那一段html代碼,既設置viewport的width爲device-width。推薦使用這個方法(其實如今的移動端頁面都有這段代碼)。第二個方法就是改用screen.width而不是使用window.innerWidth。
var scale = screen.width/320;
使用媒體查詢設置html元素font-size的大小。這個方法簡單可是工做量較多,一來是須要知道市場上全部主流的手機的屏幕尺寸,二來若是將來出現新的機型號到時候可能又會出現頁面不適配的狀況。當時這個方法確實比較簡單一點,媒體查詢的css以下:
html{ font-size:62.5%; } @media screen and (min-width:360px) and (max-width:374px) and (orientation:portrait) { html { font-size: 70.3%; } } @media screen and (min-width:375px) and (max-width:383px) and (orientation:portrait) { html { font-size: 73.24%; } } @media screen and (min-width:384px) and (max-width:399px) and (orientation:portrait) { html { font-size: 75%; } } @media screen and (min-width:400px) and (max-width:413px) and (orientation:portrait) { html { font-size: 78.125%; } } @media screen and (min-width:414px) and (max-width:431px) and (orientation:portrait){ html { font-size: 80.86%; } } @media screen and (min-width:432px) and (max-width:479px) and (orientation:portrait){ html { font-size: 84.375%; } } //如下爲ipad分辨率 @media screen and (min-width:480px)and (max-width:639px) and (orientation:portrait){ html{ font-size:93.75%;} } @media screen and (min-width:640px) and (orientation:portrait){ html{ font-size:125%;} }
rem單位值縮放法,原理上很簡單,就是讓1rem對應的px值根據屏幕的不一樣而不一樣。在某一個屏幕上頁面作好效果後,在其餘屏幕上顯示的時候,再根據該屏幕相對於標準屏的大小,對rem值進行放大和縮小。其中經過js修改rem的方法,最簡單也最好用,在不一樣的屏幕下表現也很好。
這裏對css的單位要求就不大了,你可使用rem(這裏1rem對應的px值不一樣屏幕下是不變的),也可使用px。當時使用rem是比較好的。由於使用rem你能夠方便切換其餘適配方法
這其實沒啥可講的啦,就跟普通的pc端製做頁面同樣。不過仍是有要點要提醒下的,若是你是640的設計稿你就在iphone5下製做,若是你是750的設計稿你就iphone6製做。製做完後,你喜歡的話就能夠把px轉成rem,不喜歡的話就用px。至於怎麼選擇主要仍是看你周圍妹子的顏值了。
這裏的css屬性是指css的zoom屬性而不是transform的scale屬性,由於zoom跟scale仍是有些不一樣的,最簡單的有兩個,1個是zoom的縮放是以左上角爲基點的,而scale是以元素的中心爲基點,第二個不一樣是zoom是真實的對元素進行放大和縮小,而scale僅僅只是縮放外觀,元素實際大小並無改變。
假設設計稿仍是640px,咱們在iphone5製做完頁面之後,爲了達到兼容其餘手機屏幕的效果。咱們要在頁面加一段js,這段js的做用是獲取屏幕的寬度,而後與iphone5屏幕尺寸進行比較,若是比iphone5屏幕大, 咱們就放大頁面,若是比iphone5屏幕小咱們就縮小頁面。放大和縮小頁面其實就是放大和縮小html元素。也能夠放大或者縮小body元素,不過縮放body元素有bug,html小body大就會溢出,body小html大,底部會有空白。因此縮放html元素是最好的。
(function(){ var zoom = screen.width/320; document.documentElement.style.zoom=zoom; })();
除了使用css屬性對頁面縮放外,咱們還可使用name爲viewport(視窗)的meta標籤對頁面進行縮放,該標籤是蘋果公司最早在瀏覽器中實現的,不過如今已經獲得了幾乎全部移動端瀏覽器的支持。爲了避免打臉我加了「幾乎」,其實你見到的瀏覽器都支持這一屬性,因此大膽的用吧,不用擔憂。
name爲viewport(視窗)的meta標籤有如下屬性
width | 視窗的寬度 |
initial-scale | 設置頁面的初始縮放值,爲一個數字,能夠帶小數 |
minimum-scale | 容許用戶的最小縮放值,爲一個數字,能夠帶小數 |
maximum-scale | 容許用戶的最大縮放值,爲一個數字,能夠帶小數 |
height | 設置視窗 的高度,這個屬性對咱們並不重要,不多使用 |
user-scalable | 是否容許用戶進行縮放,值爲"no"或"yes", no 表明不容許,yes表明容許 |
其中initial-scale、minimum-scale和maximum-scale屬性就是頁面進行放大和縮小的。咱們常見的meta是醬紫的。視窗的width爲device-width(設備的屏幕寬度),最小放大倍數和最大放大倍數都是1,也就是不容許頁面進行放大和縮小。
<meta name="viewport" content="width=device-width,minimum-scale=1,maximum-scale=1">
添加這種meta標籤的頁面都是使用rem單位值縮放法進行適配的。如今咱們要使用網頁縮放法就須要對這個meta標籤進行修改,可使用js獲取該meta標籤而後使用setAttribute進行修改,也可使用js直接write出該meta標籤。我使用直接write的方法,這樣比較簡單。切記這段js要加載head標籤裏。
(function(){ var scale = screen.width/320; document.write('<meta name="viewport" content="width=320,minimum-scale='+scale+',maximum-scale='+scale+'">') })()
先解釋第二地方,由於咱們是在iphone5下製做頁面,對於其餘屏幕,咱們是比較它相對於iphone5頁面的大小,再對iPhone5的頁面進行放大和縮小。因此咱們viewport的width就不能跟隨屏幕的不一樣而不一樣,就必須固定爲iphone5的屏幕寬度。
再解釋第一個地方。若是viewport的width不是device-width那麼window.innerWidth獲取的就不是屏幕的寬度。在咱們js代碼以前也沒尚未meta的因此此時使用window.innerWidth獲取的是瀏覽器的默認的viewport寬度980或者1280px。
網頁縮放法的原理是,以一個手機(一般是iphone5)爲基準,在其餘手機上顯示的時候,經過js獲取手機屏幕寬度,而後與基準手機進行對比,使用css屬性或者meta標籤對頁面擊進行縮放。網頁縮放法在實際應用中並很少。在實際應用中更多的使用rem單位值縮放法。不過這兩種方法確實也很是好用。
作遊戲的時候,咱們幾乎都是在canvas上進行製做的,這時候就要面臨一個問題就是canvas如何作適配。看起來很難,其實很簡單了。不過我當初也是花了好幾個星期才弄懂。那仍是在我學習createjs的時候。雖然我如今都沒學會createjs,可是我研究了下如何在canvas下作適配,仍是有點收穫的。canvas作適配原理同dom是同樣的,都是對頁面進行放大和縮小。原理這東西看起來都是像句廢話同樣,可是真要會應用了你就會發現,這就是一大殺器啊。你掌握某個技能你只能處理一個問題,可是你掌握了原理你就能通殺一大片。
canvas的縮放業界通用的作法是對canvas樣式的寬和高(注意注意:這裏說的是canvas的style屬性的寬和高,而不是canvas的寬和高)進行縮放的。固然縮放的方法不少了你也能夠想象其餘歪點子。鑑於我已經寫的很煩了,哎,主要是人老體弱多病,我就只介紹下寬高縮放法。
canvas頁面製做的時候仍是以一個手機爲基準,640的手機就以iphone5爲準,750的手機就以iphone6爲準。好比我是以iphone5爲準的。那麼個人canvas就能夠這樣寫
<canvas id="myC" width="320" height="568"></canvas>
css樣式以下:
html,body{ margin:0px; padding:0px; background:black; font-size: 0px; width: 100%; height: 100%; } canvas{ position: absolute; background: white; }
在這種狀況下,不一樣的手機查看網頁,寬度都是能夠正好鋪滿屏幕,高度的話若是屏幕過長,canvas下就會有空白,若是屏幕太短,頁面就會出現滾動條。
適配的代碼以下:
var can = document.getElementById("myC"); var canW=320; var canH=568; var canStyleW = screen.width; var canStyleH = screen.width/(canW/canH); can.style.width = canStyleW+"px"; can.style.height = canStyleH+"px";
在這種狀況,在不一樣的手機查看網頁,在高度上網頁會始終鋪滿屏幕的,可是在寬度上,若是手機屏幕過寬,就會出現空白。若是屏幕過窄,就會出現滾動條。如下代碼,我這對canvas加了居中處理。
適配代碼以下:
var can = document.getElementById("myC"); var canW=320; var canH=568; var canStyleW = screen.height*(canW/canH); var canStyleH = screen.height; can.style.width = canStyleW+"px "; can.style.height = canStyleH+"px "; can.style.left = (screen.width-canStyleW)/2+"px";
在這種狀況下,咱們要獲取屏幕的寬高比,而後跟iphone5的寬高比進行比較,大的話說明屏幕寬度較大高度較小,可能致使咱們的canvas顯示不全而出現上下滾動條,這時咱們就以高度爲準進行適配。小的話說明屏幕寬度偏小高度偏大,這樣就有可能致使左右方向上顯示不全。因此咱們要以寬度爲準進行適配。咱們的目的只有一個,就是隻在一屏上完整的顯示出咱們的canvas。
適配代碼以下:
var can = document.getElementById("myC"); var canW=320; var canH=568; var ratio= canW/canH; var screenRatio = screen.width/screen.height; var canStyleW,canStyleH; //寬度偏大,以高度爲準 if(screenRatio>=ratio){ canStyleW = screen.height*ratio; canStyleH = screen.height; }else{ //高度偏大,以寬度爲準 canStyleW=screen.width; canStyleH=screen.width/ratio; } can.style.width = canStyleW+"px "; can.style.height = canStyleH+"px "; can.style.left = (screen.width-canStyleW)/2+"px";
canvas適配也是採用放大和縮小,原理都很簡單。固然我以上示例中的適配方案仍是很粗糙的,在實際開發環境中確定是要優化的。我只是爲了將原理,因此並無給一個完整的方案。固然我只講了一個適配方案,確定還有其餘適配方案的,或者更好的適配方案確定也是有的。仍是那句話,原理都同樣,若是運用原理就是你的事情了。
移動端屏幕適配的大概就這些內容,要麼對元素進行放大縮小,要麼對網頁進行放大縮小。不知道你看明白了沒,不過我我的卻是很明白了,沒寫着博客前我仍是糊里糊塗的,哈哈,目的達到了。移動端適配真的沒有那麼難。但願這篇博客對你有幫助。ps一句話,有問題本身多動手寫代碼,實踐出真知。