1越败、困擾多時的問題
在這之前做Web App開發(fā)的的時候,在自適應方面一般都是寬度通過百分比骨田,高度以iPhone6跟iPhone5之間的一個平衡值寫死埠通,我們的設(shè)計稿都是iPhone5的640 * 1136標準长赞,所以高度一般取個大概值晦攒,各種圖標的寬高也是取平衡值寫死,然后部分樣式通過媒體查詢來設(shè)置得哆,例如背景圖的多倍圖脯颜、基礎(chǔ)字體大小、圖標寬高贩据。
這樣做的弊端很明顯:
做出來的頁面在各種手機端看起來的物理大卸安佟(高度)是一樣的,所以在大屏手機會覺得頁面稍小乐设,小屏手機頁面稍大
如果要使高度能更好的適應各種手機屏幕讼庇,需要寫太多的媒體查詢樣式绎巨,效率低下
全屏背景圖片跟頁面元素需要耦合時近尚,元素位置的確定尤為困難(可能需要通過百分比去確定元素的橫向位置,但始終會有誤差)
...
最近在微博上看到流云諸葛總結(jié)的一篇文章《從網(wǎng)易與淘寶的font-size思考前端設(shè)計稿與工作流》场勤,其中介紹到的幾種Web App適配方案戈锻,我們現(xiàn)在的做法恰好是跟拉勾網(wǎng)類似的簡單方案歼跟,當然就會有上面我提到的一些問題,最后經(jīng)過預研和demo測試格遭,我們采取了網(wǎng)易跟淘寶的方案哈街,其實這兩者的方案是大同小異,都是基于rem的適配方案拒迅。
2骚秦、解決問題的方案
網(wǎng)易跟淘寶的方案介紹在上面流云諸葛的文章中已經(jīng)寫的很清楚了,建議可以先看看那篇文章再閱讀下面我所說的璧微,可能會更加清晰作箍。
(1)方案的簡單介紹: 基于rem
前提:頁面元素的布局尺寸全都以設(shè)計稿為基準等比例設(shè)置。
給html根節(jié)點設(shè)置一個基礎(chǔ)font-size值前硫,然后頁面的所有元素布局均相對于該font-size值采用rem單位設(shè)定胞得。那么基礎(chǔ)的font-size值該如何取呢?
假如通過媒體查詢設(shè)置font-size屹电,只能解決一部分的情況阶剑,而且并不能完成適配,因為手機屏幕寬度類型實在太多了危号,所以font-size的取值要通過js計算牧愁,取當前viewport的deviceWidth與設(shè)計稿的寬 的 比例值,例如:我們的設(shè)計稿尺寸都是640px的葱色,iphone5的deviceWidth是320px递宅,那么計算出來的font-size值就是 320 / 640 = 0.5,因為得出的font-size太小苍狰,不方便計算办龄,且有的瀏覽器可能不兼容太小字號,所以將font-size放大100倍淋昭,所以最終計算出來的font-size為 320 / 640 * 100 = 50(px); 當然俐填,這個值是根據(jù)設(shè)計稿來計算的,所以根據(jù)計算規(guī)則翔忽,下面列出幾種常見設(shè)計稿相應的font-size值:
deviceWidth?=?320英融,font-size?=?320?/?6.4?=?50px
deviceWidth?=?375,font-size?=?375?/?6.4?=?58.59375px
deviceWidth?=?414歇式,font-size?=?414?/?6.4?=?64.6875px
deviceWidth?=?500驶悟,font-size?=?500?/?6.4?=?78.125px
可在script標簽加上如下代碼
(function()?{
document.addEventListener('DOMContentLoaded',function()?{
varhtml?=?document.documentElement;
varwindowWidth?=?html.clientWidth;
html.style.fontSize?=?windowWidth?/?6.4?+'px';
//?等價于html.style.fontSize?=?windowWidth?/?640?*?100?+?'px';
},false);
})();
//?這個6.4就是根據(jù)設(shè)計稿的橫向?qū)挾葋泶_定的,假如你的設(shè)計稿是750
//?那么?html.style.fontSize?=?windowWidth?/?7.5?+?'px';
至此材失,font-size的基礎(chǔ)值就確定好了痕鳍,而且知道該font-size值是手機deviceWidth跟設(shè)計稿的比例值 的 100倍(重要)
(2)那么頁面元素該如何設(shè)置寬高、邊距
例如:一個設(shè)計稿寬高為140px的圖標,左邊距為50px笼呆,那么它的css應該這樣寫
.icon?{
width:?1.4rem;/*?像素換算rem:140px?/?100?=?1.4rem?*/
height:?1.4rem;
margin:?0?0?0?.5rem;
}
因為html的font-size是放大了100倍熊响,所以計算rem時,要用設(shè)計稿的實際像素除以100诗赌,140px / 100 = 1.4rem; 最后實際的像素大小就會由deviceWidth跟設(shè)計稿的橫向?qū)?的 比例 自動計算出來汗茄。
如圖iPhone5下面的效果:
iPhone6的效果:
可以看出來:html的font-size動態(tài)根據(jù)deviceWidth改變,圖標的寬高铭若、邊距等也根據(jù)font-size動態(tài)按比例變化洪碳,大功告成了?不對叼屠,相信機智的你已經(jīng)看到貌似在iPhone6的下有的圖標背景錯位了偶宫。。是的环鲤,這暴露出了一個背景使用雪碧圖的一個弊端(由于font-size小數(shù)點太多纯趋,計算出實際背景圖大小background-size跟背景圖位置background-position時瀏覽器精度不夠可能就會出現(xiàn)位置的偏差(我猜的),這個后面還會詳細講解決方案)
到這里冷离,設(shè)置寬高吵冒、邊距等都OK了,接下來...
(3)其他元素的字體大小該如何設(shè)置西剥?
在流云諸葛的文章中講到痹栖,網(wǎng)易跟淘寶的做法都是使用額外的媒體查詢設(shè)置幾種字體大小,例如:
@mediascreen?and?(max-width:?320px)?{
body{font-size:?14px;}
}
@mediascreen?and?(min-width:?321px)?and?(max-width:?413px)?{
body{font-size:?16px;}
}
@mediascreen?and?(min-width:?414px)?and?(max-width:?639px)?{
body{font-size:?17px;}
}
@mediascreen?and?(min-width:?640px)?{
body{font-size:?18px;}
}
可為什么不用rem呢瞭空?后來去查了一番資料揪阿,發(fā)現(xiàn)有一種叫做點陣字體的存在(什么是點陣字體),也叫作位圖字體咆畏,位圖我們都知道南捂,跟矢量圖是有區(qū)別的,就是放大會模糊旧找,所以點陣字體也是放大會模糊的溺健,如果根據(jù)rem設(shè)置字體大小,字體會自由縮放钮蛛,可能就會導致點陣字體模糊鞭缭,所以需要設(shè)定使用幾種固定大小的字體。不過魏颓,在正常情況下岭辣,系統(tǒng)自帶的字體都是矢量字體,所以使用rem為單位是沒有問題的甸饱,除非你的網(wǎng)頁需要用到特殊的點陣字體沦童。
總結(jié):如果網(wǎng)頁沒有用到特殊的點陣字體,字體單位使用rem,如果用到了點陣字體搞动,字體需要通過媒體查詢設(shè)置幾種固定大小的字體
(4)關(guān)于背景圖片的錯位問題
上面已經(jīng)發(fā)現(xiàn)了,通過換算rem設(shè)置background-size跟background-position的時候渣刷,在一些手機型號下會出現(xiàn)背景圖錯位的情況鹦肿,可是如果不用rem設(shè)置的話,又不能達到適配的目的辅柴。(background-size箩溃、background-position的rem換算方法跟前面講的寬高設(shè)定一樣,都是設(shè)計稿尺寸(這時應該是雪碧圖的原始尺寸)除以100倍)
最后經(jīng)過嘗試碌嘀,得出了幾種解決方案:
1)如圖(推薦方案):
圖標的樣式
.icon?{
width:?1.4rem;
height:?1.4rem;
background-image:?url(sprite.png);
background-repeat:?no-repeat;
background-size:?1.4rem;
}
.icon3?{
background-position:?0?-2.8rem;
}
解決方法涣旨,如圖:
代碼如下:
.icon-fix?{
background:?none;
position:?relative;
overflow:?hidden;
}
.icon-fix:after?{
content:'';
display:?block;
width:?10000%;
height:?10000%;
position:?absolute;
left:?0;
top:?0;
background-image:?url(sprite.png);
background-repeat:?no-repeat;
background-size:?140rem;
-webkit-transform-origin:?0?0;
-webkit-transform:?scale(.01);
transform-origin:?0?0;
transform:?scale(.01);
}
.icon3:after?{
background-position:?0?-280rem;
}
所有相關(guān)代碼(傳送門)。
2)不使用雪碧圖股冗,使用單個背景圖霹陡,這個時候就不存在background-position的需要,只需設(shè)定background-size: contain;即可止状,這樣做的弊端就在于無法使用雪碧圖烹棉,圖片請求增多,適用于頁面圖標較少的情況
3)使用嵌套img標簽,通過絕對定位模擬background-position,具體請看responsive-sprites补履,這種做法需要更多的標簽服协,且img圖片只能放圖標尺寸大小一樣的雪碧圖,而且不能通過媒體查詢使用多倍圖
以上3中解決方案第一種最優(yōu)短条,當然有些特殊情況可能需要按需選擇!