基于rem响应式布局

5,446 阅读5分钟

前言

最近工作中在维护一个VUE项目,突然有一天老板和我说这个应用可能会被再用到iPad、手机等移动端,要求能在这些设备终端上流畅运行,布局样式不变。查看项目整体设计,之前就只是依据1920*1080的设备在进行开发。于是查阅资料,决定用响应式布局来完成这个要求。

响应式布局

响应式布局就是一个网站能够兼容多个终端,可以根据屏幕的大小自动调整页面的的展示方式以及布局,我们不用为每一个终端做一个特定的版本。查阅往事资料后,响应式布局方案大概有以下几种:

  • @media媒体查询
  • 通过百分比单位
  • vw/vh
  • rem
  • 移动端 viewport
  • FlexBox

响应式布局方案简要说明

1、@media媒体查询

使用@media媒体查询可以针对不同的媒体类型定义不同的样式,特别是响应式页面,可以针对不同屏幕的大小,编写多套样式,从而达到自适应的效果。例如:

@media screen and (max-width: 960px){
    body{
      background-color:#FF6699
    }
}
​
@media screen and (max-width: 768px){
    body{
      background-color:#00FF66;
    }
}
​
@media screen and (max-width: 550px){
    body{
      background-color:#6633FF;
    }
}
​

缺点:多套样式代码,麻烦

2、通过百分比单位

将样式的单位换成%,例如height、width、top、bottom 、left、right等等的属性

缺点:计算复杂、有些属性是相对于父元素,有些相对于自身,容易有问题

3、通过vw/vh

与百分比类似,都是换算单位。vw表示相对于视图窗口的宽度,vh表示相对于视图窗口高度。

4、移动端 viewport
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
​
​
width=device-width: 是自适应手机屏幕的尺寸宽度。
maximum-scale:是缩放比例的最大值。
minimum-scale:是缩放比例的最小值。
inital-scale:是缩放的初始化。
user-scalable:是用户的可以缩放的操作。
5、FlexBox

利用display属性为flex,设置弹性盒子的容器,然后定义它的属性和子元素的属性。

// container
flex-direction,主轴方向,也就是子元素排列的方向
flex-wrap,子元素能否换行展示及换行方式
flex-flowflex-directionflex-wrap 的简写形式
justify-content,子元素在主轴上的对齐方式
align-items,子元素在垂直于主轴的交叉轴上的排列方式
align-content,子元素在多条轴线上的对齐方式
​
// items
order,子元素在主轴上的排列顺序
flex-grow,子元素的放大比例,默认 0
flex-shrink,子元素的缩小比例,默认 1
flex-basis,分配剩余空间时,子元素的默认大小,默认 auto
flexflex-growflex-shrinkflex-basis 的简写
align-self,覆盖容器的 align-items 属性
​
6、通过rem

rem其实也类似百分比、vw/vh这些相对单位,rem则是相对于html元素的font-size

个人感觉完美解决所有终端的布局问题是不可能的,只能不同程度上缓解这一问题。比较这些方法后,像媒体查询、FlexBox、百分比这类需要项目改动比价大,所以放弃。另一方面又要兼顾现在的已有开发,最后选择了rem的方案。

REM布局

1、rem兼容支持

rem支持.png

满足大多数现在使用的浏览器。

2、利用flexible.js设置rem基准值

rem则是相对于html元素的font-size。使用rem首先就要先定义rem的大小,也就是定义html根元素的字体大小,一般默认为16px。

像素概念:
​
物理像素:物理像素又被称为设备像素,他是显示设备中一个最微小的物理部件。每个像素可以根据操作系统设置自己的颜色和亮度。正是这些设备像素的微小距离欺骗了我们肉眼看到的图像效果。
​
设备独立像素:也称为密度无关像素,可以认为是计算机坐标系统中的一个点,这个点代表一个可以由程序使用的虚拟像素(比如说CSS像素),然后由相关系统转换为物理像素。
​
设备像素比:简称为dpr,其定义了物理像素和设备独立像素的对应关系。它的值可以按此公式计算得到:设备像素比 = 物理像素 / 设备独立像素 (安卓一般为:1;iPhone为2或者3

这边我使用了一个flexible.js的包进行换算。

首先下载安装:

npm i -S flexible.js

引入main.js中

import flexible form 'flexible.js'flexible();

我们主要利用这个包确定不同设备下的rem单位大小,所以要对其中改变一些。

   // 源码
   function refreshRem(){
        var width = docEl.getBoundingClientRect().width;
        if (width / dpr > 540) {
            width = 540 * dpr;
        }
        var rem = width / 10;
        docEl.style.fontSize = rem + 'px';
        flexible.rem = win.rem = rem;
    }
​
​
 // 基于已知设备修改后
 function refreshRem(){
    let rem;
    var width = docEl.getBoundingClientRect().width;
    if (width / dpr > 540) {
        width = width * dpr;
    }
    if(width===1920){
        rem = width / 120;
    }else if (width===1280){
        rem = width / 80;
    }else {
        rem = width / 120;
    }
    docEl.style.fontSize = rem + 'px';
    flexible.rem = win.rem = rem;
}
3、利用postcss-pxtorem进行换算rem

利用postcss-pxtorem将项目所有的单位换算为rem,才可以响应式适配。

首先下载安装

 npm install postcss-pxtorem@5.1.1 --save 
 
 // 由于最新版本安装存在问题,换到5.1.1的版本

然后修改vue.config.js

    postcss: {
                plugins: [require('postcss-pxtorem')({
                     "rootValue": 16, // 基准值
                     "propList":["*"] // 需要做转化处理的属性,如`hight``width``margin`等,`*`表示全部
                })]
            }

然后就可以重新启动项目,并调整屏幕大小,可以发现布局已经适配了。

4、存在缺陷:

项目中某些引用框架中的样式是通过实时计算的px值得到的,这些值无法换算

最后

谨以此做笔记,方便开发测试