rem布局(等比例缩放布局)

2,224 阅读4分钟

一、来源

在css中我们一般使用px作为单位,在桌面浏览器中css的1个像素往往都是对应着电脑屏幕的1个物理像素,这可能会造成我们的一个错觉,那就是css中的像素就是设备的物理像素。但实际情况却并非如此,css中的像素只是一个抽象的单位,在不同的设备或不同的环境中,css中的1px所代表的设备物理像素是不同的。在为桌面浏览器设计的网页中,我们无需对这个津津计较,但在移动设备上,必须弄明白这点。在早先的移动设备中,屏幕像素密度都比较低,如iphone3,它的分辨率为320x480,在iphone3上,一个css像素确实是等于一个屏幕物理像素的。后来随着技术的发展,移动设备的屏幕像素密度越来越高,从iphone4开始,苹果公司便推出了所谓的Retina屏,分辨率提高了一倍,变成640x960,但屏幕尺寸却没变化,这就意味着同样大小的屏幕上,像素却多了一倍,这时,一个css像素是等于两个物理像素的。

font-size与屏幕宽建立联系,所以rem布局就产生了。

二、简介

rem布局,又称等比例缩放布局。根据fontSize等比例缩放。

eg:网易、淘宝首页

宽和高都等比缩放

  • 优点:宽和高永远成比例,不会比例失调
  • 缺点:不能体现大型手机的优势,不管手机多大,看到的内容永远那么多

分类:

  • em: font-size:2em;找父盒子,父盒子字号的2倍
  • rem: font-size:5rem; 找根元素,为html中字号的5倍

1.设备像素比(设备缩放比)

获取方法:window.devicePixelRatio

image.png

不同移动端设备的window.devicePixelRatio的值不同。 举例,当window.devicePixelRatio值为2,可以理解为1px像素等于2px物理像素。

2.可布局宽

获取方法:document.documentElement.clientWidth

3,视网膜屏幕

  • 动态设置viewport的scale,淘宝触屏版首页布局的前提是viewport的scale根据devicePixelRatio动态设置:在devicePixelRatio为1的时候,scale为1;在devicePixelRatio为2的时候,scale为0.5;在devicePixelRatio为3的时候,scale为0.3333
  • 动态计算html的font-size:font-size = deviceWidth / 10
  • 布局的时候,各元素的css尺寸=设计稿标注尺寸/设计稿横向分辨率/10
  • font-size可能需要额外的媒介查询,并且font-size不使用rem
  • 设置一个临界点,当设备竖着时横向物理分辨率大于1080时,html的font-size就不会变化了可以去访问电脑版页面了

注意:不推荐给文字字号添加rem,最好用px,但是其他变,文字不变,不可行,所以需要添加:

@media screen and (max-width:320px) {
    body{font-size:14px}
}
@media screen and (min-width:320px) and (max-width:480px) {
    body{font-size:16px}
}
@media screen and (min-width:480px) {
    body{font-size:18px}
}

三、使用

1.计算

计算公式:设备可布局宽度/设计稿宽度 * 基准fontSize值(自定义数值)

常用自定义数值为100或16

  • 100 方便计算,此时body中需要设置样式fontSize:16px
  • 16 常用fontSize

推荐:vsCode插件pxtorem可将px自动转为rem,默认基准值为16,可根据需求自定义更改。

eg:

 <script>
    //fontsize计算:设备宽/设计稿宽*100 --方便算
    //fontsize计算:设备宽/设计稿宽*16 -- 常用fontSize
    //根节点fontSize
    
    //document.documentElement.style.fontSize =
    //  document.documentElement.clientWidth / 750 * 100 + 'px'
      
          document.documentElement.style.fontSize =
      document.documentElement.clientWidth / 750 * 16 + 'px'
  </script>

eg:

<!DOCTYPE html>
<html lang="">
<style>
  body {
    font-size: 16px;
  }
</style>

<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width,initial-scale=1.0">
  <link rel="icon" href="<%= BASE_URL %>favicon.ico">
  <title>
    <%= htmlWebpackPlugin.options.title %>
  </title>
  <script>
    //fontsize计算:设备宽/设计稿宽*100--方便算
    //fontsize计算:设备宽/设计稿宽*16
    //根节点fontSize
    document.documentElement.style.fontSize =
      document.documentElement.clientWidth / 750 * 100 + 'px'
  </script>
</head>

<body>
  <noscript>
    <strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled.
        Please enable it to continue.</strong>
  </noscript>
  <!-- 入口页面 -->
  <div id="app"></div>
  <!-- built files will be auto injected -->
</body>

</html>

2.使用

(1)视口(viewport)设置

<meta name="viewport" content="initial-scale=1,maximum-scale=1, minimum-scale=1">

(2)在html上根据不同分辨率设置不同font-size,通过js计算出来

<script type="text/javascript">
    // 把尺寸放大N倍(N是window.devicePixelRatio),根据设备像素比得到屏幕宽
    var wd = document.documentElement.clientWidth*window.devicePixelRatio/10; 
    document.getElementsByTagName("html")[0].style.fontSize = wd + "px";
    // 把屏幕的倍率缩小到N分之一(N是window.devicePixelRatio)
    //var scale = 1/window.devicePixelRatio;
    //var mstr = 'initial-scale='+ scale +', maximum-scale='+ scale +', minimum-scale='+ scale +', user-scalable=no';
    //document.getElementById("vp").content = mstr;
</script>

1000px

1rem------100px root-font-size

30px------0.3rem

html 100px

div 44px-----.44rem

  • 页面里除了font-size之外的其它css尺寸都使用了rem作为单位
  • 正文的font-size需要额外的媒介查询,并且不使用rem

四、插件lib-flexible

过去常用的插件:lib-flexible

github:github.com/amfe/lib-fl…

由于viewport单位得到众多浏览器的兼容,lib-flexible这个过渡方案已经可以放弃使用,不管是现在的版本还是以前的版本,都存有一定的问题。建议大家开始使用viewport来替代此方。即amfe-flexible

五、插件amfe-flexible

安装: npm i -S amfe-flexible

使用:

<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
<script src="./node_modules/amfe-flexible/index.js"></script>

六、如何将百分比布局转成rem布局步骤

  • 通过js获取屏幕的宽度
  • 声明根元素的font-size
  • 根据比例将 px单位转成rem