前言
最近工作中在维护一个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-flow,flex-direction 和 flex-wrap 的简写形式
justify-content,子元素在主轴上的对齐方式
align-items,子元素在垂直于主轴的交叉轴上的排列方式
align-content,子元素在多条轴线上的对齐方式
// items
order,子元素在主轴上的排列顺序
flex-grow,子元素的放大比例,默认 0
flex-shrink,子元素的缩小比例,默认 1
flex-basis,分配剩余空间时,子元素的默认大小,默认 auto
flex,flex-grow,flex-shrink,flex-basis 的简写
align-self,覆盖容器的 align-items 属性
6、通过rem
rem其实也类似百分比、vw/vh这些相对单位,rem
则是相对于html元素的font-size
。
个人感觉完美解决所有终端的布局问题是不可能的,只能不同程度上缓解这一问题。比较这些方法后,像媒体查询、FlexBox、百分比这类需要项目改动比价大,所以放弃。另一方面又要兼顾现在的已有开发,最后选择了rem的方案。
REM布局
1、rem兼容支持
满足大多数现在使用的浏览器。
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值得到的,这些值无法换算
最后
谨以此做笔记,方便开发测试