移动端使用 rem 原理

发布于 2024-10-28 04:10:03 字数 3622 浏览 21 评论 0

普通适应屏幕的方式:

  1. 简单一点的页面,一般高度直接设置成固定值,宽度一般撑满整个屏,margin: 0 auto。
  2. 稍复杂一些的是利用百分比设置元素的大小来进行适配,或者利用 flex 等 css 去设置一些需要定制的宽度。
  3. 再复杂一些的响应式页面,需要利用 css3 的 media query 属性来进行适配,大致思路是根据屏幕不同大小,来设置对应的 css 样式。

rem 是依据根节点元素的字体大小来设定的, 移动端默认字体大小是 16px ,那么 10rem 默认就是 160px。

rem 基准值计算

  1. 由于我们所写出的页面是要在不同的屏幕大小设备上运行的
  2. 所以我们在写样式的时候必须要先以一个确定的屏幕来作为参考,这个就由我们拿到的视觉稿来定
  3. 假如我们拿到的视觉稿是以 iphone6 的屏幕为基准设计的
  4. 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,这是因为:

  1. 设计给的稿子双倍的原因是 iphone6 这种屏幕属于高清屏,也即是设备像素比(device pixel ratio)dpr 比较大,所以显示的像素较为清晰。
  2. 一般手机的 dpr 是 1,iphone4,iphone5 这种高清屏是 2,iphone6s plus 这种高清屏是 3,可以通过 js 的 window.devicePixelRatio 获取到当前设备的 dpr,所以 iphone6 给的视觉稿大小是(*2)750×1334 了。
  3. 拿到了 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 了,这样做的好处是:

  1. 解决了图片高清问题。
  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 方案优化版本:

  1. 使用淘宝的 flexible.js 库,但是貌似不在继续维护了-主要做了设置根节点字体和缩放。
  2. 使用简易 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

星軌x

暂无简介

文章
评论
27 人气
更多

推荐作者

qq_K6tQnV

文章 0 评论 0

Shum1n

文章 0 评论 0

表情可笑

文章 0 评论 0

qq_mmilXo

文章 0 评论 0

tmzg0000

文章 0 评论 0

离旧人

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文