最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 谈: 移动端适配Rem到底是怎么回事?

    正文概述 掘金(爱笑阿)   2021-04-09   584

    前言

    最近几年都是基于PC在开发,突然要搞移动端有点不适应,主要还是处理各终端的适配.我们通常开发的页面在PC浏览器上显示正常,但是如果放在窄屏设备(移动设备)上,会在比屏幕宽的虚拟窗口或者视口中呈现页面,以便让用户可以一次性看到所有内容,用户可以通过平移缩放查看不同区域,这是没有进行移动优化的页面,它的体验是很不好的,或者说看起来很差.

    后来,使用媒体查询,进行一些优化.但仍然存在问题,比如无法或者说很难做到更细的窗口变化体验.只能是一个区间来控制.

    meta和viewport

    简单的说viewport就是浏览器的窗口宽度高度.但是在移动端就变得复杂了,移动端的viewport宽度高度都变小,做布局需要用到两个viewport: viewportvisualviewport(虚拟的viewport)和viewportlayoutviewport(布局的viewport).

    我们在针对移动设备优化的网站需要有以下内容:

    <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no" />
    

    这里的width与height来控制视口的大小.可以将它设置为特定的像素(例如width = 666).这边设置为device-width(也有device-height),表示CSS像素的屏幕宽度,缩放比例为100%.initial-scale控制页面首次加载是的缩放级别,maximum-scale,minimum-scale和user-scalable属性控制用户如何/是否允许缩放页面。

    比如我们平时开发UI给的设计图一般按照iphone6的尺寸也就是 375.这时候我们可以设置width=375, initial-scale=1.这样子可以精确的适应这个尺寸的设备.但是如果有其他的尺寸的话,就会出现问题...这里是各种设备的尺寸参考

    rem or em

    em是一个长度单位.表示相对于父级文本的字体尺寸.如果父级字体没有设置尺寸,那就相对于浏览器默认尺寸font-size: 16px.它的值不是固定的,可以继承父级字体尺寸.

    元素的width/height/line-height/padding/margin用em为单位都是是相对于该元素的font-size

    .div1 {font-size: 16px;}
    .div2 {font-size: 2em;height: 2em;}
    .div3 {font-size: 2em;}
    
    <div class="div1">   // font-size: 16px;
        <div class="div2">1</div> // font-size: 32px;height: 64px;
        <div class="div3">1</div> // font-size: 32px;
    </div>
    

    rem是css3的相对单位.它设置的字体元素相对的是HTML根元素.也就是说我们设置html页面跟元素的font-size, 那项目里的其他节点使用rem这个单位去换算,都会依照这个根元素的值.

    其实它就是基于宽度的等比缩放.比如我们将屏幕平分100份,那我们如果知道屏幕宽度,然后去换算出来1份的宽度.然后我们开发中每次设置元素的大小都基于这个比例,那我们只需要关注屏幕宽度就可以了.换句话说,我们通过js去拿到屏幕宽度,然后去换算出每一份的值, 把这个值作为根节点的font-size,不就解决问题了.

    实际的是,浏览器字体最小是12px, 如果100份,那换算出来只有个位数大小.浏览器不支持了,我们一般都换算10份.

    这里还涉及一个概念,就是设备像素比(device pixel ratio),它是用物理像素/设备独立像素得到的.在Javascript中可以通过window.devicePixelRatio获取当前设备的dpr.我们可以通过dpr设置body的font-size来支持项目中的字体适配em这个单位.

    css:
    html {
        font-size: 37.5px; /* 375/10 */
    }
    body {
        font-size: 24px; /* 12 * dpr 修正字体大小 */
        width: 10rem;
    }
    .p1 {
        width: 5rem;
        height: 5rem;
        font-size: 1.2em; /* 字体使用em */
    }
    html:
    ...
    
    <body>
        <div class="p1">
            <div class="s1"></div>
        </div>
    </body>
    ...
    js:
    var doc = document.documentElement;
    
    function callback() {
        var rem = docEl.clientWidth / 10
        docEl.style.fontSize = rem + 'px'
        if (document.body) {
          // 设置全局body为当前dpr * 12px
          document.body.style.fontSize = (12 * dpr) + 'px'
        }
    }
    
    document.addEventListener('DOMContentLoaded', callback);
    window.addEventListener('resize', callback)
    
    

    上面的例子可以使用rem做移动端优化,但是字体使用的是em.原因就是设置根节点字体大小,会影响所以字体大小,字体大小会继承.总不能每个字体都设置字体大小...还有就是大屏用户可以选择要更大的字体还是更多的内容,如果使用rem,那就限制了用户的选择.所以在开发中,图片盒子宽度这些使用rem, 字体大小使用em.

    vue项目如何使用

    在vue项目中其实有比较成熟的方案了.lib-flexiblePostcss(pxtorem).前者所做的事情就是去获取屏幕并换算出合适的根font-size值,后者顾名思义,就是把px转为rem,方便我们在项目中可以放心使用px这个单位开发.这里是源码位置:lib-flexible,Postcss(pxtorem)

    使用起来很简单只需要:

    npm i amfe-flexible --save-dev
    npm i postcss postcss-pxtorem --save-dev
    

    然后在项目中分别引入:

    main.js
    
    import "amfe-flexible";
    
    vue.config.js
    css: {
        loaderOptions: {
          postcss: {
            plugins: [
              require("postcss-pxtorem")({
                rootValue: 37.5,
                propList: ["*"], //作用于哪些标签
              })
            ]
          }
        }
    }
    

    这样就可以了.至于amfe-flexiblepxtorem具体原理,可以去看源码.下面贴一部分amfe-flexible的代码,其实很简单:

      var docEl = document.documentElement
      var dpr = window.devicePixelRatio || 1
    
      // adjust body font size
      function setBodyFontSize () {
        if (document.body) {
          // 设置全局body为当前dpr * 12px
          document.body.style.fontSize = (12 * dpr) + 'px'
        }
        else {
          document.addEventListener('DOMContentLoaded', setBodyFontSize)
        }
      }
      setBodyFontSize();
    
      // set 1rem = viewWidth / 10
      function setRemUnit () {
        var rem = docEl.clientWidth / 10
        docEl.style.fontSize = rem + 'px'
      }
    
      setRemUnit()
    
      // reset rem unit on page resize
      window.addEventListener('resize', setRemUnit)
      window.addEventListener('pageshow', function (e) {
        if (e.persisted) {
          setRemUnit()
        }
      })
      
      if (dpr >= 2) {
        var fakeBody = document.createElement('body')
        var testElement = document.createElement('div')
        testElement.style.border = '.5px solid transparent'
        fakeBody.appendChild(testElement)
        docEl.appendChild(fakeBody)
        if (testElement.offsetHeight === 1) {
          docEl.classList.add('hairlines')
        }
        docEl.removeChild(fakeBody)
    }
    
    

    对于setBodyFontSize这个方法,官方的解释在这里.,个人觉得用来设置字体的单位em倒是也可以.

    pxtorem作为一个plugin,可想而知它做的事情就是基于webpack而完成的,对代码解析,然后把项目开发时的px转换为rem.

    总结

    一个项目做完,总得有所收获.移动端适配也算是web开发的一个经典难题,从开始到解决这个过程也是挺艰辛的,而我们现在能站在巨人的肩膀上去做事,能做的就是了解这个历程,这样能让我们有很多收获与新的感悟.

    尽管目前来说flexible不更新维护了,这边的目的在于搞清楚它到底做了什么.毕竟现在浏览器对rem是挺友好的.等后续vw/vh可以完美支持了,可以修改方案.

    加油.


    起源地下载网 » 谈: 移动端适配Rem到底是怎么回事?

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元