你有没有遇到过以下这种问题(页面错乱):查看代码,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