rem适配方案

3,593 阅读6分钟

rem适配方案

1. 介绍

1.1. 动态 Rem 方案既能实现页面级整体缩放,又能个性化控制某些元素不缩放

1.2. 基于这个原理,对于需要适配屏幕等比缩放的元素可以选用 rem 作为单位,对于不需要等比缩放的元素依旧使用 px 作为单位

1.3只要调整html标签的 font-size,就能让所有使用 rem 单位的元素跟随着发生变化,而使用 px 单位的元素不受影响

2. 实施

设计稿宽度是750px,设计稿上一个div的标注尺寸是375px(宽度是设计稿宽度的一半),我们可以

  • 设置 html 的 font-size 为 100*屏幕宽度/设计稿宽度
  • 在写 CSS 时设置 div 的宽度是 3.75rem(计算时用设计稿标注值除以100),边框宽度为 1px

3. 疑问

    3.1 难点之处
      若屏幕宽度375  设计图纸750  375/750=0.5  0.5*100=50px  则html的fontSize为50px  
      那么此刻1rem == 50px   3.75rem = 187.5px(是屏幕宽度的一半)  7.5rem = 375px(是整个屏幕的大小)
      
      (1)在750px设计图中p标签的宽度为450px   450/750
      (2)那么按照这个比例,在375px的屏幕上应该显示为多少?    x/375
        按照数学公式来算的话:
          450/750 = x/375   推出x=200px
      (3)那么200px应该在设置多少rem呢?   
        因为1rem = 50px  那么 200/50 = 4rem  因此需要4rem才能符合在设计中的400px要求
      
      此时是不是很意外,设计图要求400px,我们写4rem   150px,我们写1.5rem,为什么呢?
      因为比例取得好,我们取了100px作为基数来乘以 (屏幕宽度/设计稿宽度)   
      
      1.如果取100, 375/750*100=50px  即1rem=50px  
      此时设计图有一个div,分别的尺寸为300 420 
​
      当div尺寸为300px,基数取100时:
        设计图尺寸   手机上尺寸应
          300        x
          ————  =   ————    x=>150   手机上尺寸应该为150px 转化为rem  150/50=3rem 
          750       375
​
        设计图尺寸   手机上尺寸应
          420        x
          ————  =   ————    x=>210   手机上尺寸应该为210px 转化为rem  210/50=4.2rem 
          750       375
​
        你会发现最后换算的结果总是与设计图中div的尺寸相差了100倍 那么就是我们那时取的100基数
        那么写的时候设计图300px 那么只要取小100倍即可
      
      2.如果取50, 375/750*50=25px  即1rem=25px  
      此时设计图有一个div,分别的尺寸为300 420 
​
      当div尺寸为300px,基数取100时:
        设计图尺寸   手机上尺寸应
          300        x
          ————  =   ————    x=>150   手机上尺寸应该为150px 转化为rem  150/25=6rem 
          750       375
​
        设计图尺寸   手机上尺寸应
          420        x
          ————  =   ————    x=>210   手机上尺寸应该为210px 转化为rem  210/50=8.4rem 
          750       375
​
        你会发现最后换算的结果总是与设计图中div的尺寸相差了50倍 那么就是我们那时取的50基数
        那么写的时候设计图300px 那么需要除以100乘以2
      
      3.那好像可以直接不用设置基数  方案2
        375/750 = 0.5  1rem=0.5px  
        如果div是750的,在手机上不就是750rem吗? 750rem = 750*0.5=375px 刚好是手机的屏幕大小 
        那不就是设计图多少,实际你写多少就行,实际上把尺寸缩小一倍
        
        发现写750rem好像太大了,想写小一点,那么就有了上面的基数产生,将font-size=0.5放大100倍
        那么就是50px,最后写7.5rem就行
        
        当 1rem = 0.5px 时,
            设计图div尺寸      手机
              375px         375rem=375*0.5=187.5px  div占设计图一半 摆在手机也是占一半 
        
        当 1rem = 50px 时,
            设计图div尺寸      手机
              375px         3.75rem=3.75*50=187.5px  同上 
      
    3.2 为什么要用 100 来乘以屏幕宽度/设计稿宽度?
      其实 100 只是随便选取的一个值,我们也可以随便其他任意值比如 50。如果选 100,
      设计稿中某个元素标注的尺寸是 375px,我们可以很快速的计算出 3.75rem。如果 html 的 font-size 
      设置为 50*屏幕宽度/设计稿宽度,那么 div 的宽度就应该是 7.5rem了。换算起来就没那么直观了。
​

4. 版本1:没设置任何的边界值

    // 封装rem适配H5项目
    ; (function rem() { 
      let dw = 750  // 设计图宽度
      let sw = window.screen.width  // 屏幕宽度
      let fontSize = (sw / dw * 100)        // 方案1
      // let fontSize = (sw / dw)            // 方案2
      let oHtml = document.getElementsByTagName('html')[0]
      oHtml.style.fontSize = fontSize + 'px'
      window.onresize = function (event) {
        rem();
      }
    })();

版本2:设置边界值

    // 封装rem适配H5项目
    ; (function rem() { 
      let dw = 750  // 设计图宽度
      let sw = window.screen.width  // 屏幕宽度
      let fontSize = (sw / dw * 100)        // 方案1
      // let fontSize = (sw / dw)            // 方案2
      let oHtml = document.getElementsByTagName('html')[0]
      oHtml.style.fontSize = fontSize + 'px'
      
      // 设置边界
      const boundary = ()=>{
        if(sw>580){
          oHtml.style.fontSize = 64 + 'px'
        }
        if(sw<300){
          oHtml.style.fontSize = 40 + 'px'
        }
      }
      boundary()
​
      window.onresize = function (event) {
        rem();
        boundary();
      }
    })();

5.例子

<!-- <div id="app">
    <div class="nomal_wrap">正常尺寸</div>
    <div class="rem_aa"></div>
  </div>   -->
​
​
  <div id="test">
    <nav>
      <div class="title">
        <img src="http://rcabqe9ry.hn-bkt.clouddn.com/20220524173501.png" alt="">
      </div>
      <div class="upload">下载APP</div>
    </nav>
    <div class="list-item">
      <img src="http://rcabqe9ry.hn-bkt.clouddn.com/20220524174945.png" alt="">
      <img src="http://rcabqe9ry.hn-bkt.clouddn.com/20220524174958.png" alt="">
      <img src="http://rcabqe9ry.hn-bkt.clouddn.com/20220524175109.png" alt="">
    </div>
​
    <div style="border-bottom:10px solid rgb(235, 229, 229);"></div>
​
    <div class="new-list">
      <div class="item">
        <div class="txt">
          <div>日民众游行抗议:阻止日美"侵略中国" 别把日本变战场</div>
          <div class="editor">环球时报</div>
        </div>
        <div class="img"><img src="http://rcabqe9ry.hn-bkt.clouddn.com/20220524195507.png" alt=""></div>
      </div>
    </div>
​
    <div class="new-list">
      <div class="item">
        <div class="txt">
          <div>日民众游行抗议:阻止日美"侵略中国" 别把日本变战场</div>
          <div class="editor">环球时报</div>
        </div>
        <div class="img"><img src="http://rcabqe9ry.hn-bkt.clouddn.com/20220524195507.png" alt=""></div>
      </div>
    </div>
​
    <div class="new-list">
      <div class="item">
        <div class="txt">
          <div>日民众游行抗议:阻止日美"侵略中国" 别把日本变战场</div>
          <div class="editor">环球时报</div>
        </div>
        <div class="img"><img src="http://rcabqe9ry.hn-bkt.clouddn.com/20220524195507.png" alt=""></div>
      </div>
    </div>
  </div>
​
​
  <div class="aaa"></div>
* {
      margin: 0;
      padding: 0;
    }
​
​
    .nomal_wrap {
      width: 250px;
      height: 100px;
      background-color: pink;
      font-size: 16px;
    }
​
    .rem_aa {
      background-color: cadetblue;
      color: aliceblue;
      line-height: 50px;
​
      /* 需要随屏幕等比缩放,使用rem单位,比如设计稿中标注的32px这里写成0.32rem */
      width: 3rem;
      /*不需要缩放的部分用px*/
      height: 50px;
​
      border: 1px solid #ccc;
      margin-bottom: 20px;
    }
​
​
​
​
    /* 新闻音乐案例 */
    /* 
      把宽 高 padding margin font-size 都用rem进行等比例缩放 border可以不需要
      使用vscode插件:px to rem & rpx & vw (cssrem)  alt+z 快捷键可以一键转换为rem
    */
    /* 导航 */
    nav {
      display: flex;
      justify-content: space-between;
      padding: 0 .3rem;
      box-sizing: border-box;
      height: 1.12rem;
      background-color: #d43c33;
      align-items: center;
    }
​
    nav .title img {
      display: block;
      width: 3.2rem;
    }
​
    nav .upload {
      font-size: .28rem;
      color: #fff;
    }
​
​
    /* 图片 */
    .list-item {
      display: flex;
      flex-wrap: wrap;
      width: 100%;
    }
​
    .list-item img {
      width: 33.33%;
    }
​
​
    /* 新闻 */
    .new-list {
      font-size: .32rem;
      box-sizing: border-box;
      margin: 0 .2rem;
      padding: .2rem 0;
      /* background-color: pink; */
      /* border这种不需要rem等比例缩放 写成px即可 */
      border-bottom: 1px solid #e4e4e4;
    }
​
    .new-list .item {
      display: flex;
      justify-content: space-around;
    }
​
    .new-list .item .img {
      margin-left: .24rem;
    }
​
    .new-list .item .img img {
      width: 1.92rem;
      height: 1.28rem;
    }
​
    .new-list .item .editor {
      /* background-color:chocolate; */
      border: .02rem solid #d43c33;
      margin-top: 0.2rem;
      font-size: .28rem;
      width: 3rem;
      height: 0.6rem;
    }
​
​
    .aaa {
      height: 20px;
      background-color: #d43c33;
​
    }
// 封装rem适配H5项目
    ; (function rem() {
      let dw = 750  // 设计图宽度
      let sw = window.screen.width  // 屏幕宽度
      let fontSize = (sw / dw * 100)        // 方案1
      // let fontSize = (sw / dw)            // 方案2
      let oHtml = document.getElementsByTagName('html')[0]
      oHtml.style.fontSize = fontSize + 'px'
​
      // 设置边界
      const boundary = () => {
        if (sw > 580) {
          oHtml.style.fontSize = 64 + 'px'
        }
        if (sw < 300) {
          oHtml.style.fontSize = 40 + 'px'
        }
      }
      boundary()
​
      window.onresize = function (event) {
        rem();
        boundary();
      }
    })();

效果图:

d4cfe2756fba61870eecb193c5e8fb6