首先看看下面這行代碼:html
<meta name="viewport" content="width=device-width, user-scalabel=no">
有過移動端開發經驗的同窗是否是對上面這句代碼很是熟悉?它可能最多見的響應式設計的 viewport
設置之一,而我今天介紹的這種方法也是利用了 meta 標籤設置 viewport
來支持大部分的移動端屏幕分辨率。java
<meta name="viewport">
使得移動端網站只須要按照固定的寬度設計並實現,就能在任何主流的移動設備上都能看到符合設計稿的頁面,包括 Android 4+、iPhone 4+。iPhone 的適配比較簡單,只須要設置 width
便可。好比:android
<!-- for iPhone --> <meta name="viewport" content="width=320, user-scalable=no" />
這樣你的頁面在全部的 iPhone 上,不管是 寬 375 像素的 iPhone 6 仍是寬 414 像素的 iPhone 6 plus,都能顯示出定寬 320 像素的頁面。web
Android 上的適配被戲稱爲移動端的 IE,確實存在着不少兼容性問題。Android 以 4.4 版本爲一個分水嶺,首先說一說相對好處理的 Android 4.4+app
爲了兼容性考慮,Android 4.4 以上拋棄了 target-densitydpi
屬性,它只會在 Android 設備上生效。若是對這個被廢棄的屬性感興趣,能夠看看下面這兩個連接:iphone
咱們能夠像在 iPhone 上那樣設置 width=320
以達到咱們想要的 320px 定寬的頁面設計。測試
<!-- for Android 4.4+ --> <meta name="viewport" content="width=320, user-scalable=no" />
做爲 Android 相對較老的版本,它對 meta 中的 width 屬性支持得比較糟糕。以三星 Note II 爲例,它的 device-width 是 360px。若是設置 viewport 中的 width (如下簡稱 vWidth
) 爲小於等於 360 的值,則不會有任何做用;而設置 vWidth
爲大於 360 的值,也不會使畫面產生縮放,而是出現了橫向滾動條。網站
想要對 Android 4.0 ~ 4.3 進行支持,仍是不得不借助於頁面縮放,以及那個被廢除的屬性:target-densitydpi
。spa
target-densitydpi 一共有四種取值:low-dpi (0.75), medium-dpi (1.0), high-dpi (1.5), device-dpi。在 Android 4.0+ 的設備中,device-dpi 通常都是 2.0。我使用手頭上的三星 Note II 設備 (Android 4.1.2) 進行了一系列實驗,獲得了下面這張表格:
target-densitydpi | viewport: width | body width | 屏幕可視範圍寬度 |
---|---|---|---|
low-dpi (0.75) | vWidth <= 320 | 270 | 270 |
vWidth > 320 | vWidth* | 270 | |
medium-dpi (1.0) | vWidth <= 360 | 360 | 360 |
vWidth > 360 | vWidth* | 360 | |
high-dpi (1.5) | vWidth <= 320 | 540 | 540 |
320 < vWidth <= 540 | vWidth* | vWidth* | |
vWidth > 540 | vWidth* | 540 | |
device-dpi (2.0)** | vWidth <= 320 | 720 | 720 |
320 < vWidth <= 720 | vWidth* | vWidth* | |
vWidth > 720 | vWidth* | 720 |
首先能夠看到 320px 是個特別詭異的臨界值,低於這個臨界值後就會發生超出咱們預期的事情。綜合考慮下來,仍是採用 target-densitydpi = device-dpi
這一取值。若是你想要以 320px 做爲頁面的寬度的話,我建議你針對安卓 4.4 如下的版本設置 width=321
。
若是 body 的寬度超過屏幕可視範圍的寬度,就會出現水平的滾動條。這並非咱們指望的結果,因此咱們還要用到縮放屬性 initial-scale
。計算公式以下:
Scale = deviceWidth / vWidth
這樣的計算式不得不使用 JS 來實現,最終咱們就能獲得適配 Android 4.0 ~ 4.3 定寬的代碼:
var match, scale, TARGET_WIDTH = 320; if (match = navigator.userAgent.match(/Android (\d+\.\d+)/)) { if (parseFloat(match[1]) < 4.4) { if (TARGET_WIDTH == 320) TARGET_WIDTH++; var scale = window.screen.width / TARGET_WIDTH; document.querySelector('meta[name="viewport"]').setAttribute('content', 'width=' + TARGET_WIDTH + ', initial-scale = ' + scale + ', target-densitydpi=device-dpi'); } }
其中,TARGET_WIDTH
就是你所指望的寬度,注意這段代碼僅在 320-720px 之間有效哦。
若是是 iPhone 或者 Android 4.4+ 的機器,在使用 scale 相關的屬性時要很是謹慎,包括 initial-scale
, maximum-scale
和 minimum-scale
。 要麼保證 Scale = deviceWidth / vWidth,要麼就儘可能不用。來看一個例子:
在縮放比不能保證的狀況下,即便設置一樣的 width
和 initial-scale
後,二者的表現也是不一致。具體兩種機型採用的策略如何我尚未探索出來,有興趣的同窗能夠研究看看。最省事的辦法就是在 iPhone 和 Android 4.4+ 上不設置 scale 相關的屬性。
結合上面全部的分析,你能夠經過下面這段 JS 代碼來對全部 iPhone 和 Android 4+ 的手機屏幕進行適配:
var match, scale, TARGET_WIDTH = 320; if (match = navigator.userAgent.match(/Android (\d+\.\d+)/)) { if (parseFloat(match[1]) < 4.4) { if (TARGET_WIDTH == 320) TARGET_WIDTH++; var scale = window.screen.width / TARGET_WIDTH; document.querySelector('meta[name="viewport"]').setAttribute('content', 'width=' + TARGET_WIDTH + ', initial-scale = ' + scale + ', target-densitydpi=device-dpi'); } } else { document.querySelector('meta[name="viewport"]').setAttribute('content', 'width=' + TARGET_WIDTH); }
若是你不但願你的頁面被用戶手動縮放,你還能夠加上 user-scalable=no
。不過須要注意的是,這個屬性在部分安卓機型上是無效的哦。
有興趣的同窗能夠拿這個測試頁面來測測本身的手機,別忘了改 viewport
哦。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=250, initial-scale=1.5, user-scalable=no"> <title>Document</title> <style> body { margin: 0; } div { background: #000; color: #fff; font-size: 30px; text-align: center; } .block { height: 50px; border-bottom: 4px solid #ccc; } #first { width: 100px; } #second { width: 200px; } #third { width: 300px; } #fourth { width: 320px; } #log { font-size: 16px; } </style> </head> <body> <div id="first" class="block">100px</div> <div id="second" class="block">200px</div> <div id="third" class="block">300px</div> <div id="fourth" class="block">320px</div> <div id="log"></div> <script> function log(content) { var logContainer = document.getElementById('log'); var p = document.createElement('p'); p.textContent = content; logContainer.appendChild(p); } log('body width:' + document.body.clientWidth) log(document.querySelector('[name="viewport"]').content) </script> </body> </html>
本文的版權歸做者 鄒潤陽 全部,採用 Attribution-NonCommercial 3.0 License。任何人能夠進行轉載、分享,但不可在未經容許的狀況下用於商業用途;轉載請註明出處。感謝配合!