“h5”布局之如何修复在某些机型rem不准确的问题

之前在做一个移动端的项目(rem)的时候,发生过一个特别神奇的事情,大概就是在大多数机型都是正常的,但是个别机型,或宽度超出窗口的宽度,产生横向滚动条。

付上初版rem规则代码

(function (doc, win) {
  var pxOneRem = 0;
  // 我们的规则是 窗口100%宽度的rem = 10rem
  // 我们在写css的时候,也要按照这个标准来写
  
  /*
    css 公式,假如设计稿的宽度是750px,那么w变量的元素,实际的rem值是
   这是一个简单换算公式,实际项目中可以使用px2rem-loader配置
    function c (w) {
      const width100 = 750
      const remClient = 10; 
      return Number((10*(w/750)).toFixed(3))
    }
  */
  var remClient = 10;
  var docEl = doc.documentElement,
    resizeEvt = 'orientationchange' in window ? 'orientationchange' : 'resize',
    // 计算html的font-size
    recalc = function () {
      var clientWidth = docEl.clientWidth;
      if (!clientWidth) return;
      // 这里定一个页面的最大宽度
      clientWidth = clientWidth > 900 ? 900 : clientWidth;
      pxOneRem = clientWidth / remClient;
      docEl.style.fontSize = pxOneRem + 'px';
    };
  if (!doc.addEventListener) return;
  win.addEventListener(resizeEvt, recalc, false);
  doc.addEventListener('DOMContentLoaded', recalc, false);
  //当dom加载完成时,或者 屏幕垂直、水平方向有改变进行html的根元素计算
})(document, window);

这样看来是没有什么问题的,但是在某些机型(如华为、小米某些安卓机型),就会发生出现一些滚动条(宽度超出)的现象,调试发现就一些地方使用10rem的宽度(认为是100%)造成了宽度超出。

我们这里假设我们的pxOneRem为32(px),我们现在要计算10rem的元素究竟真实的宽度为多少。那么有些小伙伴肯定会认为10 x 32 = 320,其实准确的计算方式并不是这样,实际上rem真实的计算方式是:rem值*根目录上的font-size数值的一个字的真实宽度= 实际像素(10 x dom(style:font-size:32px).width)

发现使用上述两种计算方式出来的值是误差的,说明font-size=16px的一个字,他的真实宽度并不一定就是16px,所以我们需要对rem的pxOneRem 进行纠错。

(function (doc, win) {
  var pxOneRem = 0;
  var remClient = 10;
  var docEl = doc.documentElement,
    resizeEvt = 'orientationchange' in window ? 'orientationchange' : 'resize',
    recalc = function () {
      var clientWidth = docEl.clientWidth;
      if (!clientWidth) return;
      clientWidth = clientWidth > 900 ? 900 : clientWidth;
      pxOneRem = clientWidth / remClient;
      docEl.style.fontSize = pxOneRem + 'px';
      // 纠错函数
      function adapt(){  
        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
      }
      pxOneRem = pxOneRem * pxOneRem / adapt();
      docEl.style.fontSize = pxOneRem + 'px'
    };
  if (!doc.addEventListener) return;
  win.addEventListener(resizeEvt, recalc, false);
  doc.addEventListener('DOMContentLoaded', recalc, false);
})(document, window);

纠错逻辑是往dom里插入一个宽度为rem为1rem元素,计算出他的真实宽度,与pxOneRem做一个等比例计算。举例,理想中我们计算的出来的1rem的像素为 pxOneRem,而实际表现的值却为adapt(),那么纠错后的pxOneRem, 我们假设为x,那么 pxOneRem / x = adapt() / pxOneRem。

可能理解起来不直观,再用大白话描述一下这个公式,假设我们我们现在有一个屏幕为320px宽度,pxOneRem初步计算出来为32px,实际adapt计算出来的1rem的元素宽度却为36px,说明我们premx(32)大了,我们需要缩小这个premx以使得让1rem的元素宽度adapt算出来等于32px。所以 32/x = 36/32 => pxOneRem / x = adapt() / pxOneRem。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 了解真实的『REM』手机屏幕适配rem 作为一个低调的长度单位,由于手机端网页的兴起,在屏幕适配中得到重用。 使用...
    张宪宇阅读 2,279评论 0 5
  • 说到前端页面的布局方案,可以从远古时代的Table布局说起,然后来到 DIV+CSS布局,之后有了Float布局,...
    841只阅读 1,469评论 1 3
  • 作者:HelKyle链接:http://www.w3cplus.com/css/when-to-use-em-vs...
    红叶丶秋鸣阅读 3,283评论 0 3
  • 网上很多都说会pc网页开发,也就会了mobile网页开发。那么实际呢也是如此,但是对于新手来说却摸不着头脑无从下手...
    亚讯阅读 25,217评论 1 17
  • 今天带给大家的是一个被历史的严肃性与政治性掩盖的爱情故事。爱情无关年龄,无关身份,无关性别,也无关爱恨情仇。有人为...
    北方的一墨阅读 215评论 1 0