你有沒有遇到過以下這種問題(頁面錯亂):查看代碼,html的font-size設置正常,在瀏覽器和絕大部分手機上也正常,可是在某些手機上頁面元素爲何就大了或小了呢?是rem佈局不許了嗎?css
非也,實際上是系統字體大小的問題,這類問題常見於安卓設備上,並且是內嵌在APP裏面的H5頁面。html
問題因素
出現這個問題有幾個因素:
1.用rem佈局的H5頁面
2.頁面內嵌在APP的webview中
3.手機 設置 修改了默認字體大小,以下圖個人小米手機示例。web
知足以上三個因素,在不少手機上都會出現這個問題。瀏覽器
解決方案
方案一(獲取系統字體大小)
通常設計稿750px,爲了便於計算,咱們設1rem = 100px;也就是1rem = 1 * htmlFontSize (htmlFontSize 爲 html 元素的字體大小),固然在iPhone6 375px寬的屏幕上,htmlFontSize 爲50px。微信
其實,htmlFontSize 除了以px爲單位外,還能夠用百分比做爲單位,好比你能夠設置htmlFontSize的大小爲312.5%,頁面的佈局效果與設置htmlFontSize 大小爲50px是同樣的效果。app
那麼問題來了,設置爲百分比單位的時候,這個百分比值是怎麼計算出來的呢?函數
瀏覽器默認字體大小爲 16px,當咱們使用百分比做爲根節點 html 的字體大小時,rem 的計算方式就會改成佈局
defaultFontSize = 16px
1rem = 1 * htmlFontSize * defaultFontSize
好比375像素寬設備上:字體
1rem = 1 * 312.5% *16 = 50 px
這與咱們的實際狀況相符,可是在有些 Android 手機上,瀏覽器或 webview 的默認字體是隨着系統設置的字體改變的。這樣就會致使默認字體大於或小於 16px。從這個思路出發,咱們只須要找到系統設置的字體大小就能夠正確的計算htmlFontSize的值了。flex
因而寫一個函數來獲取defaultFontSize的值:
//獲取系統默認字體大小
//designWidth 設計稿的寬度
//rem2px 設計稿寬度下,1rem的寬度
function adapt(designWidth, rem2px){
var d = window.document.createElement('div');
d.style.width = '1rem';
d.style.display = "none";
var head = window.document.getElementsByTagName('head')[0];
head.appendChild(d);
var defaultFontSize = parseFloat(window.getComputedStyle(d, null).getPropertyValue('width'));
return defaultFontSize
};
而後再結合咱們以前計算 htmlFontSize 的函數能夠獲得完整的計算方式:
!(function(doc, win, designWidth, rem2px) {
var docEl = doc.documentElement,
defaultFontSize = adapt(designWidth, rem2px),
resizeEvt = 'orientationchange' in window ? 'orientationchange' : 'resize',
recalc = function() {
var clientWidth = win.innerWidth
|| doc.documentElement.clientWidth
|| doc.body.clientWidth;
if (!clientWidth) return;
if (clientWidth < 750) {
docEl.style.fontSize = clientWidth / designWidth * rem2px / defaultFontSize * 100 + '%';
} else {
docEl.style.fontSize = '625%';
}
};
if (!doc.addEventListener) return;
win.addEventListener(resizeEvt, recalc, false);
doc.addEventListener('DOMContentLoaded', recalc, false);
})(document, window, 750, 100);
親測有效,看官能夠回去一試!
方案二(獲取html元素實際寬度)
以前搜索了好久,也沒有看到很好的解決方案,包括像淘寶的flexible適配方案也沒有解決這個問題,今天寫文章的時候在搜索結果的後面幾頁,有一篇文章一樣也是介紹這個問題的,解決思路仍是有點不太同樣的,這位同窗是直接去獲取html的實際大小和理想值的比值,而後作 htmlFontSize 的相應處理,這裏一併給你們分享!
通常,咱們動態計算好html的font-size以後,咱們就啥都不幹了,就走了。可是,咱們如今知道了,咱們設置的大小不必定是真實的大小,因此,咱們須要在設置完字體大小以後,再去從新獲取一下html的font-size,看看實際的這個值,和咱們設置的是否是同樣。若是不同,就要根據比例再設置一次。
function htmlFontSize(){
var h = Math.max(document.documentElement.clientHeight, window.innerHeight || 0);
var w = Math.max(document.documentElement.clientWidth, window.innerWidth || 0);
var width = w > h ? h : w;
width = width > 720 ? 720 : width
var fz = ~~(width*100000/36)/10000
document.getElementsByTagName("html")[0].style.cssText = 'font-size: ' + fz +"px";
var realfz = ~~(+window.getComputedStyle(document.getElementsByTagName("html")[0]).fontSize.replace('px','')*10000)/10000
if (fz !== realfz) {
document.getElementsByTagName("html")[0].style.cssText = 'font-size: ' + fz * (fz / realfz) +"px";
}
}
方案三(客戶端固定webview字體大小)
推進移動端同窗進行處理,在APP內直接設置webview的默認字體大小。
如:在每一個webview配置webview.getSettings().setTextZoom(100)就能夠了。
一樣處理方式的有如微信,你們能夠先修改下手機系統字體大小,而後再去體驗微信裏面的遊戲/購物(這裏是用web實現的),發現根本不會受影響(首先我查看源碼看了下里面的頁面,是用了rem佈局的)。
其實我建議用第三種方案進行處理,由於這樣體驗更統一,可是想一想,若是用戶確實有調大字體的需求,或者有看小字體的習慣,用戶設置字體大小,你就是不給人家任何變化,也是至關很差的體驗呢。
因此微信就在 設置-通用-字體大小裏面內置了設置字體大小的功能,幫助用戶獲得更好的閱讀體驗。
固然你在微信裏面調整了字體大小再去看 遊戲/購物 發現仍是沒有變化,這裏就不清楚微信是直接固定了系統字體大小仍是經過js處理rem佈局頁面的,若是有微信的同窗能看到的話,有興趣能夠回答一下,謝謝!
擴展補充
擴展
微信的 iOS 版的調整字體大小使用的是經過給 body 設置 -webkit-text-size-adjust:120% 屬性實現的,Android 則是經過 Java 調用 webview 的 API 設置字體大小。
補充
若是是用方案一,並且要繼續解決 rem佈局加載閃爍問題,那麼就要將原來的媒體查詢所有換成百分比單位的,代碼以下:
@media (min-width: 320px){html{font-size: 266.667%;} }
@media (min-width: 360px){html{font-size: 300%;} }
@media (min-width: 375px){html{font-size: 312.5%;;} }
@media (min-width: 384px){html{font-size: 320%;} }
@media (min-width: 414px){html{font-size: 345%;} }
@media (min-width: 448px){html{font-size: 373.333%;} }
@media (min-width: 480px){html{font-size: 400%;} }
@media (min-width: 512px){html{font-size: 426.667%;} }
@media (min-width: 544px){html{font-size: 453.333%;} }
@media (min-width: 576px){html{font-size: 480%;} }
@media (min-width: 608px){html{font-size: 506.667%;} }
@media (min-width: 640px){html{font-size: 533.333%;} }
@media (min-width: 750px){html{font-size: 625%;;} }
可是,很是嚴重的問題。引入文件時,方案一計算的js文件必需要放在媒體查詢的css文件前面,否則就會出現 htmlFontSize 一直都是100%的計算錯誤,這個問題目前我尚未找到其餘解決方案,只能先放在前面了。(腳本就十幾行,放在前面對DOM的渲染影響也不大)
更新1024
看這篇文章的文末反思部分 rem佈局加載閃爍問題。
1.html{font-size: 50px;}//這個必定寫
2.JS動態計算和密集的媒體查詢二選一
基於此和解決rem佈局在webview中頁面錯亂問題,咱們若是是選擇JS動態計算,因計算的原理須要,咱們要將JS(或JS引入)放在CSS(或者CSS引入)以前。媒體查詢方案沒有要求。--------------------- 原文:https://blog.csdn.net/u013778905/article/details/77972841