我在網上看過不少相關的資料,都在說淘寶適配方案和網易適配方案。說了dpr,meta等好多概念,說實話我感受寫的都好複雜,跟我本身想的有出入。新學東西我總想找到這個東西設計的出發點,但我沒在這些文章中找出來。在看了些如今主流網站的代碼後,以爲本身有了一點心得,因此獻醜拿來分享下,但願對你有點幫助javascript
既然是適配咱們開始確定要有一個參考屏幕,這裏咱們先提早肯定下面全部的例子都是以iphone6的屏幕(寬度爲375px
)爲參照。一般設計稿是2倍的設計稿,因此咱們拿到的設計稿設計稿最終寬度爲750px
。css
屏幕適配最終的目標或者說本質就是實現 等比縮放。html
如今各大網站雖然方案有差別,但步驟和目的實際上是同樣的,主要分爲如下幾步:前端
爲何要有個基準?由於咱們不但願每種屏幕寫一種佈局樣式,因此咱們須要有一個基準來隨屏幕寬度變化,咱們只要根據基準來肯定咱們的css值,就能夠適配全部的屏幕了。java
這就是適配的所有了,下面咱們來看看這幾步能夠用什麼方案來解決。git
基準是什麼?爲了簡單基準咱們當作單位,因此咱們須要找一個能變化的單位,思考下,css中哪些單位能夠變化?rem
是以根字體的大小來肯定本身的值的,符合條件。因此咱們可讓根字體隨屏幕變化而變化,咱們直接用rem
進行佈局能夠了。github
下一步就是肯定基準值,咱們這裏就是肯定根字體的值。爲了方便咱們計算咱們能夠設置一個很容易計算的值,好比咱們可讓設計稿中1rem=100px
,那麼寫起來就是sass
// 屏幕寬度 / 7.5 = 1rem
// 或
// 100vw / 7.5 = 1rem
複製代碼
這兩種在這個例子中是同樣的,而後咱們寫樣式的時候用rem
作爲單位就能夠了,好比設計稿上有一個寬度爲80px
的div
元素,咱們只須要這樣寫:bash
div {
width: .8rem;
}
複製代碼
若是你仍是嫌每次手動計算麻煩,能夠用如今樣式預處理器(如less、sass)中的mixin的來幫你或者使用js來動態計算。app
到這裏咱們的適配就說完了。你可能會問dpr、meta頭設置視圖寬度那些東西怎麼沒看到,我明明在不少文章看到這些概念。別急,其實這些都是爲了解決一個問題,下面咱們就來講說這個問題
hairline
是啥?hairline其實就是很細的線,不少設計師特別喜歡用這種線,讓咱們前端頭大🙄。這種線直接用0.5px
行嗎?這在之前一些舊的屏幕上是不行的,會被自動修正爲1px
,咱們都知道。
可是現代不少手機都是高倍屏,即一個css像素會有多個物理像素,這樣顯示的圖像更細膩而且更清晰,有的已經支持css使用小數,這種狀況下咱們能夠直接使用像0.5px
來寫出這種寬度的線了。這裏有個概念,物理像素數和css像素被稱爲設備像素比
,也就是咱們常常說的dpr了
物理像素數 / css像素數 = dpr
複製代碼
dpr
的值能夠經過window.devicePixelRadio
來獲取。
問題好像已經解決了。可是咱們前端還有很重要的一部分的工做是兼容,若是遇到不支持這種小數css寫法的怎麼辦?咱們想個很通用的解決方案,那就是縮放,好比咱們把1px
寬度的線縮小一半就能獲得0.5px
寬度的線了。
爲了讓咱們全部1px
寬度縮爲一個物理像素寬,咱們就須要讓頁面寬度爲屏幕css寬度 * dpr
。而後咱們在這個寬度下寫1px
寬度的線,最後再縮小dpr
倍咱們就能夠得獲得1物理像素寬度了。
爲了實現讓頁面變爲屏幕css寬度 * dpr
的寬的目的,咱們須要按比例改變咱們上面的適配方案。
假如如今dpr=3
,咱們就須要讓頁面寬度爲 375 * 3 = 1125,而咱們的設計稿是750。咱們就須要讓咱們的基準值成比例變化
// 屏幕寬度 / 7.5 => 屏幕寬度 / 7.5 / 2 * 3
複製代碼
如今咱們獲得尺寸爲屏幕css寬度 * dpr
的頁面了,爲了讓頁面徹底顯示在屏幕中咱們須要在html中設置meta頭(不瞭解這些的本身查下,有不少資料)
<meta name="viewport" content="width=屏幕css寬度 * dpr">
複製代碼
而後縮小dpr倍變成
<meta name="viewport" content="width=屏幕css寬度 * dpr,initial-scale=1/dpr,minimum-scale=1/dpr,maximum-scale=1/dpr,user-scalable=no">
複製代碼
到這裏,咱們全部東西都講完了,但願你已經理解了爲何會有那麼多寫法不一樣的適配方案了,他們都是異曲同工。
最後附上如今淘寶和網易的部分代碼,你能夠本身直接去他們網站找到這些代碼。你應該能根據這些代碼分析他們的方案了,這些留給你本身思考和分析了
手機淘寶網部分適配代碼
! function (e, t) {
var n = t.documentElement,
d = e.devicePixelRatio || 1;
function i() {
var e = n.clientWidth / 3.75;
n.style.fontSize = e + "px"
}
if (function e() {
t.body ? t.body.style.fontSize = "16px" : t.addEventListener("DOMContentLoaded", e)
}(), i(), e.addEventListener("resize", i), e.addEventListener("pageshow", function (e) {
e.persisted && i()
}), 2 <= d) {
var o = t.createElement("body"),
a = t.createElement("div");
a.style.border = ".5px solid transparent", o.appendChild(a), n.appendChild(o), 1 === a.offsetHeight && n.classList.add("hairlines"), n.removeChild(o)
}
}(window, document)
複製代碼
手機網易新聞網部分適配代碼
html {
font-size: 13.33333vw
}
@media screen and (max-width: 320px) {
html {
font-size:42.667px;
font-size: 13.33333vw
}
}
@media screen and (min-width: 321px) and (max-width:360px) {
html {
font-size:48px;
font-size: 13.33333vw
}
}
@media screen and (min-width: 361px) and (max-width:375px) {
html {
font-size:50px;
font-size: 13.33333vw
}
}
@media screen and (min-width: 376px) and (max-width:393px) {
html {
font-size:52.4px;
font-size: 13.33333vw
}
}
@media screen and (min-width: 394px) and (max-width:412px) {
html {
font-size:54.93px;
font-size: 13.33333vw
}
}
@media screen and (min-width: 413px) and (max-width:414px) {
html {
font-size:55.2px;
font-size: 13.33333vw
}
}
@media screen and (min-width: 415px) and (max-width:480px) {
html {
font-size:64px;
font-size: 13.33333vw
}
}
@media screen and (min-width: 481px) and (max-width:540px) {
html {
font-size:72px;
font-size: 13.33333vw
}
}
@media screen and (min-width: 541px) and (max-width:640px) {
html {
font-size:85.33px;
font-size: 13.33333vw
}
}
@media screen and (min-width: 641px) and (max-width:720px) {
html {
font-size:96px;
font-size: 13.33333vw
}
}
@media screen and (min-width: 721px) and (max-width:768px) {
html {
font-size:102.4px;
font-size: 13.33333vw
}
}
@media screen and (min-width: 769px) {
html {
font-size:102.4px;
font-size: 13.33333vw
}
}
複製代碼
本文原文更新在個人github上,這裏是原文連接。若是文章有任何錯誤或不許確之處,歡迎指出,很是感謝!