做爲一個前端開發人員,咱們的任務是將UI設計師的圖稿運用計算機語言呈如今用戶面前。而如今的設備大小尺寸不一,近年來智能手機的普及更是讓網頁的用戶大部分來源與手機,因此讓不一樣大小的移動端屏幕都能較好的還原設計稿就成了一個前端開發者須要解決的當務之急。我查閱了大量資料和進行了一些實踐,下面是我對移動端適配的一些認識。css
首先咱們來談談咱們在電腦端用的字體單位px和em前端
在國內的網站中大多都是使用px做爲字體單位,只有百度作了個可調的表率。而在大洋彼岸,幾乎全部的主流站點都使用em做爲字體單位,也就是可調的。他們爲何要用em做爲單位呢,主要有一下幾個緣由編程
Firefox可以調整px和em,可是96%以上的中國網民使用IE瀏覽器(或內核)。瀏覽器
px像素(Pixel): 相對長度單位。像素px是相對於顯示器屏幕分辨率而言的。
__em:__是相對長度單位。相對於當前對象內文本的字體尺寸。如當前對行內文本的字體尺寸未被人爲設置,則相對於瀏覽器的默認字體尺寸。app
任意瀏覽器的默認字體高都是16px。全部未經調整的瀏覽器都符合: 1em=16px。那麼12px=0.75em,10px=0.625em。爲了簡化font-size的換算,須要在css中的body選擇器中聲明 Font-size=62.5%,這就使em值變爲 16px*62.5%=10px, 這樣12px=1.2em, 10px=1em, 也就是說只須要將你的原來的px數值除以10,而後換上em做爲單位就好了。iphone
em有以下特色:
1. em的值並非固定的;
2. em會繼承父級元素的字體大小。
因此咱們在寫CSS的時候,須要注意兩點:
1. body選擇器中聲明Font-size=62.5%;
2. 將你的原來的px數值除以10,而後換上em做爲單位;
3. 從新計算那些被放大的字體的em數值。避免字體大小的重複聲明。ide
下面咱們來談談移動端的適配方案佈局
首先講講一個基本概念字體
移動前端中常說的 viewport (視口)就是瀏覽器顯示頁面內容的屏幕區域。網站
移動端的viewport太窄,爲了能更好爲CSS佈局服務,因此提供了兩個viewport:虛擬的visual viewport和佈局的layout viewport。
通常移動設備的瀏覽器都默認設置了一個viewport 元標籤,定義一個虛擬的layout viewport(佈局視口),用於解決早期的頁面在手機上顯示的問題。iOS, Android基本都將這個視口分辨率設置爲 980px,因此pc上的網頁基本能在手機上呈現,只不過元素看上去很小,通常默承認以經過手動縮放網頁。
這裏是一個小demo,分別是加了
和沒加頁面的效果
visual viewport(視覺視口)備物理屏幕的可視區域,屏幕顯示器的物理像素,一樣尺寸的屏幕,像素密度大的設備,硬件像素會更多。例如iPhone的物理像素:
iPhone6 Plus:1242 * 2208
ideal viewport(理想視口)一般是咱們說的屏幕分辨率。
dip (設備邏輯像素)跟設備的硬件像素無關的。一個 dip 在任意像素密度的設備屏幕上都佔據相同的空間。
好比MacBook Pro的 Retina (視網膜)屏顯示器硬件像素是:2880 * 1800。當你設置屏幕分辨率爲 1920 * 1200 的時候,ideal viewport(理想視口)的寬度值是1920像素, 那麼 dip 的寬度值就是1920。設備像素比是1.5(2880/1920)。設備的邏輯像素寬度和物理像素寬度(像素分辨率)的關係知足以下公式:
邏輯像素寬度*倍率 = 物理像素寬度
而移動端手機屏幕一般不能夠設置分辨率,通常都是設備廠家默認設置的固定值,換句話說 dip 的值就是 ideal viewport(理想視口)(也就是分辨率)的值,好比,iPhone的屏幕分辨率:
iPhone5 :分辨率 320 * 568,物理像素 640 * 1136,@2x
iPhone6:分辨率 375 * 667,物理像素 750 * 1334,@2x
iPhone6 Plus :分辨率 414 * 736,物理像素1242 * 2208,@3x
因此咱們須要使用viewport元標籤控制佈局
一般用到的適配代碼
<meta name="viewport" content="width=device-width,initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
這裏是每一個屬性的詳細介紹
爲了是適應佈局,咱們通常將width設爲device-width。
width=device-width 也就是將layout viewport(佈局視口)的寬度設置 ideal viewport(理想視口)的寬度。網頁縮放比例爲100%時,一個CSS像素就對應一個 dip(設備邏輯像素),而layout viewport(佈局視口)的寬度,ideal viewport(理想視口)的寬度(一般說的分辨率),dip 的寬度值是相等的。
initial-scale用於指定頁面的初始縮放比例:
由於分辨率和物理像素的關係,因此咱們就須要經過js來肯定頁面的初始縮放比例,下面是控制初始縮放比例的代碼。後面會進行解釋
var i = e.navigator.appVersion.match(/iphone/gi) ? e.devicePixelRatio :1, a = 1 / i,
rem其實和em很是類似,在w3c中是這樣描述rem的
font size of the root element.
它的用法和em差很少,區別是em是針對父元素的font-size作計算,而rem是相對與根元素作計算。咱們在移動端使用rem做爲全部大小的單位來解決適配的問題。
咱們設置根元素font-size的大小,應該是不一樣屏幕設置不同的。好比一個740大的屏幕,咱們會把它的font-size設爲76px;而一個370大的屏幕,咱們會把它的font-size設爲34px,這要根據屏幕大小而言。
因此,咱們須要編寫一個js文件來適應不一樣的屏幕
這是某個網站的移動適配js,這裏經過這個文件作一些解釋
!function(e) { function t() { e.rem = d.getBoundingClientRect().width / 16, d.style.fontSize = e.rem + "px"; } var n, i = e.navigator.appVersion.match(/iphone/gi) ? e.devicePixelRatio :1, a = 1 / i, d = document.documentElement, o = document.createElement("meta"); if (e.dpr = i, e.addEventListener("resize", function() { clearTimeout(n), n = setTimeout(t, 300); }, !1), e.addEventListener("pageshow", function(e) { e.persisted && (clearTimeout(n), n = setTimeout(t, 300)); }, !1), d.setAttribute("data-dpr", i), o.setAttribute("name", "viewport"), o.setAttribute("content", "initial-scale=" + a + ", maximum-scale=" + a + ", minimum-scale=" + a + ", user-scalable=no"), d.firstElementChild) d.firstElementChild.appendChild(o); else { var m = document.createElement("div"); m.appendChild(o), document.write(m.innerHTML); } t(); }(window), document.addEventListener("DOMContentLoaded", function() { var e = document.createElement("input"); e.type = "hidden", e.value = '{"platform": "qq_qzone_weixin_weibo_copy","title":"","desc": "","image":"","comment": "", "url":"","callback":"shareCallback()"}', e.id = "app_share_conf", document.getElementsByTagName("body")[0].appendChild(e); }, !1);
咱們在開發過程當中拿到的設計稿都是以px做爲單位的,那咱們在進行移動端編程的時候該怎樣對應rem大小呢?
e.rem = d.getBoundingClientRect().width / 16
這段代碼的意思是把屏幕分紅16份,根元素的font-size就等於屏幕大小/分紅份數。固然咱們不必定要把屏幕分紅16份,好比淘寶的Flexible.js將屏幕分紅10份。
前面已經提到,針對不一樣的設備,屏幕分辨率和物理像素的倍速不一樣因此咱們要經過獲取設備來設置縮放比例。
var i = e.navigator.appVersion.match(/iphone/gi) ? e.devicePixelRatio :1, a = 1 / i,
關於移動適配的meta標籤,咱們是不用事先編寫的,經過這個js文件,將自動建立meta標籤。