前言
對于 rem 相信很多做移動端頁面的大胸弟都不陌生,用rem加百分比來做自適應那是爽的不能再爽。至少切一般的h5頁面是沒多大問題的。但是今天卻讓我發(fā)現(xiàn)某個三星機下面竟然出現(xiàn)頁面顯示不正常的問題,大部分安卓機跟蘋果機還是正常顯示的,也就是說,這尼瑪百分百是機型兼容性問題。經(jīng)過查看確定了是rem引起的問題。既然拋出了問題,那就得找原因跟解決辦法。
在這里,我首先想到的是安卓系統(tǒng)的問題,經(jīng)過各種百度,也證實了我的想法。網(wǎng)上有些人提出android4.4、android4.4.4系統(tǒng)下的部分安卓機就存在rem計算失常的情況。除此之外,撇開操作系統(tǒng)不說,部分機型還是存在這個問題,特別是三星的手機!如果你遇到了這個問題,那么很有可能就是三星的手機了。私下去問了個大牛,說是三星的機子確實存在這么個情況,主要是機子的屏幕引起的。ok,原因也知道了,那么就提出解決方案。
首先,先說說我自己是怎么做移動端適配工作的,其實也是摸索過來的,如有不正確的地方還請指正。
- 確定移動端頁面的寬度范圍,通常我會取 320px - 768px ,一個是最小的尺寸,一個是ipad的,再往上感覺就沒必要在手機展示了,也不美觀。所以css的容器經(jīng)常會這樣寫,給予一個寬度范圍:
#indexContainer{
width: 100%;
min-width: 320px;
max-width: 768px;
min-height: 100%;
font-size: .24rem;
overflow-y: hidden;
background-image: url(../../common/images/indexBg.png);
background-position: 50% 0;
background-size: 100% 100%;
background-repeat: no-repeat;
}
2.全局加載一個js文件,用于動態(tài)計算html的fontSize值。因為rem是根據(jù)根節(jié)點html的字體大小而動態(tài)改變的,所以不同寬度下計算得到不同的font-size,相應地就可以用rem去作為頁面元素的長度單位實現(xiàn)自適應了。下面是基于美術稿720px所寫的計算fontSize的js:
(function(_D){
var _self = {};
_self.resizeEvt = 'orientationchange' in window ? 'orientationchange' : 'resize';
_self.Html = _D.getElementsByTagName("html")[0];
_self.widthProportion = function(){
var p = Number((_D.body&&_D.body.clientWidth||_self.Html.offsetWidth)/720).toFixed(3);
return p>1.067?1.067:p<0.444?0.444:p;
};
_self.changePage = function(){
_self.Html.setAttribute("style","font-size:"+_self.widthProportion()*100+"px");
};
_self.changePage();
if (!document.addEventListener) return;
window.addEventListener(_self.resizeEvt,_self.changePage,false);
document.addEventListener('DOMContentLoaded', _self.changePage, false);
})(document);
解釋下上面的代碼,widthProportion 函數(shù)是用來返回當前與設計稿(720px)的比率的。因為頁面存在一個寬度范圍,即(320px - 768px), 所以在這兩個臨界點大于取大,小于取小。這樣 頁面放到很大或者很小的時候字體大小也有個臨界值。監(jiān)聽 resize事件和DomContentLoaded事件,從而改變字體大小。即 changePage 函數(shù)。font-size最后乘以100是為了方便計算rem。如拿到720px的設計稿,高度250px就對應2.5rem。
3.經(jīng)過實踐,發(fā)現(xiàn)部分安卓機出現(xiàn)的該問題大多是rem計算出來的font-size總是要比預期要大一些,甚至聽說部分三星的手機還有計算出來比預期小的情況,這簡直是駭人聽聞。參考網(wǎng)上各種方法,最后綜合提出一種最為穩(wěn)妥的處理方法,就是在計算font-size值時多一步判斷來進行頁面font-size的reset。代碼經(jīng)改動如下:
(function(_D){
var _self = {};
_self.resizeEvt = 'orientationchange' in window ? 'orientationchange' : 'resize';
_self.Html = _D.getElementsByTagName("html")[0];
_self.widthProportion = function(){
var p = Number((_D.body&&_D.body.clientWidth||_self.Html.offsetWidth)/720).toFixed(3);
return p>1.067?1.067:p<0.444?0.444:p;
};
_self.changePage = function(){
_self.Html.setAttribute("style","font-size:"+_self.widthProportion()*100+"px");
_self.correctPx();
};
_self.correctPx = function(){
var docEl = document.documentElement;
var clientWidth = docEl.clientWidth;
if (!clientWidth || clientWidth > 768) return;
var div = document.createElement('div');
div.style.width = '1.4rem';
div.style.height = '0';
document.body.appendChild(div);
var ideal = 140 * clientWidth / 720;
var rmd = (div.clientWidth / ideal);
console.log(rmd);
if(rmd > 1.2 || rmd < 0.8){
docEl.style.fontSize = 100 * (clientWidth / 720) / rmd + 'px';
document.body.removeChild(div);
}
};
_self.changePage();
if (!document.addEventListener) return;
window.addEventListener(_self.resizeEvt,_self.changePage,false);
document.addEventListener('DOMContentLoaded', _self.changePage, false);
})(document);
對比上面,多加了個correctPx函數(shù)。在每次計算完頁面的fontSize后,對某個實際元素的大小進行判斷,如果對比原來的比例有0.2以上的出入,那就用這個比例去重新設置頁面的fontSize。如果是正常情況,就不會執(zhí)行頁面fontSize重新這一步。至此,問題也算是解決了。
總結
對比設置css來控制html的font-size我覺得用js來控制更為簡潔,而且代碼改動量小。在做移動端適配的時候比較容易忽略的點是給頁面設置一個寬度范圍,還有就是怎樣根據(jù)ui給你的設計稿做出高保真的頁面。安卓機兼容這塊坑還是太多了。能填一個是一個吧,惡心。