移动端使用 rem 原理
普通适应屏幕的方式:
- 简单一点的页面,一般高度直接设置成固定值,宽度一般撑满整个屏,margin: 0 auto。
- 稍复杂一些的是利用百分比设置元素的大小来进行适配,或者利用 flex 等 css 去设置一些需要定制的宽度。
- 再复杂一些的响应式页面,需要利用 css3 的 media query 属性来进行适配,大致思路是根据屏幕不同大小,来设置对应的 css 样式。
rem 是依据根节点元素的字体大小来设定的, 移动端默认字体大小是 16px ,那么 10rem 默认就是 160px。
rem 基准值计算
- 由于我们所写出的页面是要在不同的屏幕大小设备上运行的
- 所以我们在写样式的时候必须要先以一个确定的屏幕来作为参考,这个就由我们拿到的视觉稿来定
- 假如我们拿到的视觉稿是以 iphone6 的屏幕为基准设计的
- iPhone6 的屏幕大小是 375px,iPhone4/4s,5/5s 屏幕宽度是 320,
因此目前我们的 rem 基准值是:37.5px
rem = window.innerWidth/10 /*37.5px*/
为什么要除以 10 呢,其实这个值是随便定义的,因为不想让 html 的 font-size 太大,当然也可以选择不除,只要在后面动态 js 计算时保证一样的值就可以
如何通过 css 动态的设置 html 的 fontSize?
通过 css 的 media query 去匹配
@media (min-device-width : 375px) and (max-device-width : 667px) and (-webkit-min-device-pixel-ratio : 2){
html{font-size: 37.5px;}
}
利用 js 去动态的去计算 rem 的基准值
document.getElementsByTagName('html')[0].style.fontSize = window.innerWidth / 10 + 'px';
设计稿以 iPhone6 为准的话,dpr 是 2,那么我们拿到设计稿的时候,都会将设计稿的标注或者自己量出来的尺寸/2,这是因为:
- 设计给的稿子双倍的原因是 iphone6 这种屏幕属于高清屏,也即是设备像素比(device pixel ratio)dpr 比较大,所以显示的像素较为清晰。
- 一般手机的 dpr 是 1,iphone4,iphone5 这种高清屏是 2,iphone6s plus 这种高清屏是 3,可以通过 js 的 window.devicePixelRatio 获取到当前设备的 dpr,所以 iphone6 给的视觉稿大小是(*2)750×1334 了。
- 拿到了 dpr 之后,我们就可以在 viewport meta 头里,取消让浏览器自动缩放页面,而自己去设置 viewport 的 content 例如(这里之所以要设置 viewport 是因为我们要实现 border1px 的效果,假如我给 border 设置了 1px,在 scale 的影响下,高清屏中就会显示成 0.5px 的效果)
window.devicePixelRatio 是一个只读属性,它返回的是一个物理像素在当前显示的设备(垂直) 上的一个独立像素的比例。没有回调函数或者是事件来监听这个值的改变。
meta.setAttribute('content', 'initial-scale=' + 1/dpr + ', maximum-scale=' + 1/dpr + ', minimum-scale=' + 1/dpr + ', user-scalable=no');
配合 sass 或者 less 就比较方便了:
@function px2rem($px){
$rem : 75px;
@return ($px/$rem) + rem;
}
双倍屏幕下就是 375*2/100 = 75
,这样就可以完全按照视觉稿上的尺寸来了。不用在/2 了,这样做的好处是:
- 解决了图片高清问题。
- 解决了 border 1px 问题(我们设置的 1px,在 iphone 上,由于 viewport 的 scale 是 0.5,所以就自然缩放成 0.5px)
在 iphone6 下的例子:我们使用动态设置 viewport,在 iphone6 下,scale 会被设置成 1/2 即 0.5,其他手机是 1/1 即 1.
meta.setAttribute('content', 'initial-scale=' + 1/dpr + ', maximum-scale=' + 1/dpr + ', minimum-scale=' + 1/dpr + ', user-scalable=no');
以上原文转自 这里
依据上面的方案,目前自己所使用的 rem 方案优化版本:
- 使用淘宝的 flexible.js 库,但是貌似不在继续维护了-主要做了设置根节点字体和缩放。
- 使用简易 js 动态计算根节点字体大小
!(function(doc, win) {
var timer, docEle = doc.documentElement,
evt = "onorientationchange" in window ? "orientationchange": "resize",
setFontSize = function() {
var width = docEle.clientWidth;
var rem = 750 / 10;
width && (docEle.style.fontSize = ((width / 750) * rem) + "px");
};
win.addEventListener(evt,
function() {
clearTimeout(timer);
timer = setTimeout(setFontSize, 200);
},
false);
doc.addEventListener("DOMContentLoaded", setFontSize, false);
}(document, window));
上面两种都使用了 gulp 通过将 px2rem 了。不使用 rem 解决可以用另一种办法,通过判断屏幕 dpr 然后进行页面 zoom 缩放,这种方式比较简单,但是不适合做全屏。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
下一篇: 压缩和增强手写笔记
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论