在進(jìn)入正文之前,我們需要先了解一些viewport相關(guān)的概念。
viewport
一般來說竹揍,我們?cè)诖a的最開始會(huì)寫上這么一句
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
移動(dòng)端瀏覽器可以在一個(gè)比屏幕更寬的虛擬”窗口“中渲染頁面,從而無需將所有頁面都?jí)嚎s進(jìn)小屏幕里(那樣會(huì)把很多沒有針對(duì)移動(dòng)端進(jìn)行優(yōu)化的站點(diǎn)打亂)。用戶可以通過平移和縮放來瀏覽頁面的不同區(qū)域径簿。比如我們把一個(gè)頁面的寬度寫成了10000px,那么我們照樣可以通過平移縮放來看到這個(gè)頁面嘀韧,當(dāng)然這是不可取的篇亭,所以我們就需要以上代碼,將viewport的width設(shè)置為設(shè)備的寬度锄贷,縮放的倍數(shù)是1译蒂,且不讓用戶進(jìn)行縮放(這個(gè)可以根據(jù)實(shí)際業(yè)務(wù)場(chǎng)景來設(shè)置)曼月。經(jīng)過以上設(shè)置,我們就可以開始進(jìn)入愉快寫代碼的第一步了~
- 物理像素DP(device pixels)和css像素
物理像素一般在設(shè)備出廠的時(shí)候就被設(shè)置好了柔昼,也叫設(shè)備像素哑芹,單 位是pt(point)
,pt
是一個(gè)物理單位捕透,指的是組成顯示器屏幕的絕對(duì)長度聪姿。我們買電視機(jī)的時(shí)候,會(huì)說乙嘀,我買個(gè)70寸的電視機(jī)末购。
1英寸=72pt
px(pixel)是一個(gè)虛擬的單位,也是一個(gè)相對(duì)的單位乒躺。根據(jù)《CSS權(quán)威指南》的像素理論中的解釋:
顯示器上的小色框是像素
CSS2.1 建議采用96ppi(pixels per inch)招盲,這是Windows機(jī)器常用的度量。Mac系統(tǒng)下用的是72ppi嘉冒。
摘錄來自: Eric Meyer. “CSS權(quán)威指南第三版”曹货。 iBooks.
1px=1/ppi英寸
通過inch就可以連接器pt和px的關(guān)系。
- 設(shè)備獨(dú)立像素DIP(Device independent Pixel)
設(shè)備獨(dú)立像素讳推,也稱為邏輯像素顶籽,也叫css像素。我們可以通過screen.width或者screen.height輸出银觅。比如iPhone的css像素就是375px*667px礼饱,iPhone 6 則采用了750×1334分辨率的屏幕,PPI值為326究驴。
物理像素和css像素的計(jì)算公式是:
DPR = 物理像素/CSS像素
css reset樣式重置
為什么要進(jìn)行css reset操作镊绪?
css reset主要是因?yàn)閔tml標(biāo)簽在瀏覽器中都有各自的默認(rèn)樣式。
比如: p 標(biāo)簽有上下邊距洒忧,strong標(biāo)簽有字體加粗樣式蝴韭,em標(biāo)簽有字體傾斜樣式。不同瀏覽器的默認(rèn)樣式之間也會(huì)有差別熙侍,例如ul默認(rèn)帶有縮進(jìn)的樣式榄鉴,在IE 下,它的縮進(jìn)是通過margin實(shí)現(xiàn)的蛉抓,而Firefox下庆尘,它的縮進(jìn)是由padding實(shí)現(xiàn)的。在切換頁面的時(shí)候巷送,瀏覽器的默認(rèn)樣式往往會(huì)給我們帶來麻煩驶忌,影響開發(fā)效率。所以解決的方法就是一開始就將瀏覽器的默認(rèn)樣式全部去掉惩系,更準(zhǔn)確說就是通過重新定義標(biāo)簽樣式位岔。
常用的適配方案
- flex
<div class="content">
<div class="con">
<div class="a"></div>
</div>
<div class="con">
<div class="a"></div>
</div>
<div class="con">
<div class="a"></div>
</div>
</div>
.content{
display: flex;
}
.con{
display: flex;
justify-content:center;
align-items:center;
flex:1;
height: 300px;
background: #999;
color:#fff;
border:1px solid #000;
}
.a{
width: 30px;
height: 30px;
background: #f00;
}
-
媒體查詢media query
一個(gè)媒體查詢由一個(gè)可選的媒體類型和零個(gè)或多個(gè)使用媒體功能的限制了樣式表范圍的表達(dá)式組成如筛,例如寬度、高度和顏色抒抬。媒體查詢杨刨,添加自CSS3,允許內(nèi)容的呈現(xiàn)針對(duì)一個(gè)特定范圍的輸出設(shè)備而進(jìn)行裁剪擦剑,而不必改變內(nèi)容本身妖胀。
我們把上面flex的css換掉其中a的樣式,來看一下media query的作用惠勒。
.a{
background:#f00;
}
@media (max-width: 800px) {
.a {
width:50px;
height:50px;
font-size:12px;
color:#2e9900;
}
}
@media (min-width:801px) and (max-width:1000px) {
.a {
width:200px;
height:200px;
font-size:20px;
color:blue;
}
}
@media (min-width: 1001px) {
.a {
width:450px;
height:450px;
font-size:40px;
}
}
- transform-scale
其實(shí)我自己覺得transform-scale
是一個(gè)不錯(cuò)的適配方式赚抡,簡單明了,而且暫時(shí)也沒有遇到過什么適配方面的大坑纠屋,相對(duì)而言還比較精確涂臣。
處理方式很簡單,樣式完全按照設(shè)計(jì)稿的px
來寫售担。然后在js中計(jì)算當(dāng)前頁面的寬度與設(shè)計(jì)稿的寬度的比赁遗,直接對(duì)body
進(jìn)行transform-scale
的縮放。
如果非要說有什么問題的話族铆,那就是如果需要考慮橫屏受眾岩四,那就得針對(duì)一些橫屏的狀態(tài)做一些特殊處理。還有就是transform-scale
縮小沒有問題哥攘,放大的話剖煌,會(huì)導(dǎo)致頁面模糊。
這個(gè)方案就看自己業(yè)務(wù)需求來選擇了逝淹。
- rem
rem算是一個(gè)使用很廣泛的適配方案了耕姊。
實(shí)現(xiàn)的方式就是給html根節(jié)點(diǎn)設(shè)置一個(gè)font-size,作為頁面計(jì)算的基準(zhǔn)栅葡。一般這個(gè)基準(zhǔn)會(huì)根據(jù)設(shè)計(jì)稿來定箩做。
假設(shè)設(shè)計(jì)稿的寬度是750px,那最初我們可以將font-size設(shè)為75px妥畏,頁面寬度就是10rem。
然后在頁面中用js動(dòng)態(tài)獲取一下當(dāng)前頁面寬度安吁,計(jì)算出頁面寬度與750px的比例醉蚁,獲取當(dāng)前頁面根節(jié)點(diǎn)上應(yīng)該帶上多大的font-size,假設(shè)當(dāng)前頁面寬度是375px鬼店,那么根節(jié)點(diǎn)上帶上的font-size應(yīng)該是37.5px网棍。
這個(gè)方案是一個(gè)與dpr無關(guān)的方案,就是說完全依賴的是設(shè)備獨(dú)立像素而不是設(shè)備的物理像素妇智,這樣就會(huì)存在一個(gè)問題滥玷,在dpr較大的高清屏上氏身,可能導(dǎo)致模糊。
當(dāng)然惑畴,我們也是可以加上dpr來計(jì)算根節(jié)點(diǎn)的font-size的蛋欣。
- flexible.js
flexible是手淘的一套解決方案,這是一套dpr
相關(guān)的解決方案如贷。
實(shí)現(xiàn)的原理是:
flexible將頁面分成100份陷虎,即100a,10a=1rem杠袱。比如尚猿,頁面寬度為750px,那么一份為75px,1rem=75px。
通過js動(dòng)態(tài)獲取當(dāng)前頁面的dpr和設(shè)備獨(dú)立像素徙鱼。拿iPhone 8 plus舉例南窗,得到dpr是3,設(shè)備獨(dú)立像素是414px舷蒲。那么html上寫的font-size的大小是這么計(jì)算的:
dpr * 414 / 10
最終得到的font-size值是124.2px,然后在meta的initial-scale里會(huì)根據(jù)dpr再進(jìn)行一下頁面縮放,這就可以保證頁面的精細(xì)程度惨恭。
但是如果在meta viewport中手動(dòng)設(shè)置了initial-scale,那么不管js獲取到的dpr是多少耙旦,都會(huì)強(qiáng)制認(rèn)為dpr是手動(dòng)設(shè)置的值脱羡;
手淘處理文字的方式,并沒有采用rem免都,因?yàn)閞em計(jì)算出的小數(shù)锉罐,在對(duì)小數(shù)敏感度不一樣的機(jī)型上會(huì)導(dǎo)致展示誤差,且小于12px的文字并不會(huì)正常被渲染绕娘。也會(huì)導(dǎo)致一些line-height的問題脓规。
- vm
隨著前端技術(shù)的演進(jìn),vw這個(gè)單位又走上了歷史的舞臺(tái)险领。
在CSS Values and Units Module Level 3中和Viewport相關(guān)的單位有四個(gè)侨舆,分別為vw
、vh
绢陌、vmin
和vmax
挨下。
- `vw`:是Viewport's width的簡寫,`1vw`等于`window.innerWidth`的`1%`
- `vh`:和`vw`類似,是Viewport's height的簡寫脐湾,`1vh`等于`window.innerHeihgt`的`1%`
- `vmin`:`vmin`的值是當(dāng)前`vw`和`vh`中較小的值
- `vmax`:`vmax`的值是當(dāng)前`vw`和`vh`中較大的值
常見的屏幕適配問題和解決方案
- line-height
一般客戶端的webview會(huì)有一個(gè)默認(rèn)的line-height臭笆,大概會(huì)是在22px的樣子。我們有可能會(huì)遇到一個(gè)問題就是,在我們?cè)O(shè)置好一個(gè)line-height之后愁铺,但是渲染出來的文字相對(duì)于我們預(yù)想的是偏上的鹰霍。導(dǎo)致這個(gè)問題的原因是,我們?cè)O(shè)置的line-height是小于webview預(yù)設(shè)的最小line-height的茵乱,這樣我們?cè)O(shè)置的那個(gè)值會(huì)被忽略茂洒。
解決的方案是:
盡量保證font-size是大于12px的,將line-height設(shè)置為1似将,使用上下padding使文字居中获黔。在一些必須需要font-size小于12px的地方,可以先放font-size大于12px在验,再用transform:scale去縮小玷氏。
但是這一點(diǎn)從實(shí)際經(jīng)驗(yàn)來看,我更偏愛手淘的方案腋舌,根據(jù)dpr或者mediaquery設(shè)置一個(gè)固定的字體盏触,這就需要和設(shè)計(jì)同學(xué)定下一個(gè)設(shè)計(jì)規(guī)范。 - 中英文的字號(hào)一樣块饺,但是實(shí)際高度卻不一樣
文字的大小赞辩,取決于設(shè)計(jì)文字的人,就像我們前幾天遇到的英文比中文同字號(hào)小的問題授艰,如果光靠上下的padding來寫的話辨嗽,那就可能會(huì)出現(xiàn)純英文或者數(shù)字那塊會(huì)比較矮。 - 1像素問題
產(chǎn)生原因:因?yàn)閐pr高的設(shè)備下淮腾,寫的1像素糟需,實(shí)際是比1的dpr倍。
解決方案:1)如果整體縮放頁面的話谷朝,1像素的線也會(huì)被一起縮放
2)可以將線條所在元素用transform-scale縮小 - 如果設(shè)計(jì)師在設(shè)計(jì)稿上使用的文字很細(xì)洲押,比如華文細(xì)黑這樣的,那前端為了適配更完美圆凰,可以用一個(gè)樣式-webkit-font-smoothing: antialiased;
- 在移動(dòng)端我們寫了overflow:scroll;之后杈帐,滑動(dòng)可能并不能像我們預(yù)料中的那么順暢,可以使用樣式-webkit-overflow-scrolling: touch;
- 如果input或button的有怪異的默認(rèn)樣式,嘗試appearance:none;(-webkit-appearance:none;)