# 响应式布局

  • 在不同设备上正常使用

  • 一般主要处理屏幕大小的问题

  • 主要方法:

    • 隐藏+折行+自适应空间
    • 媒体查询/rem/viewport/media query

# 一、媒体查询 @media

CSS3 中的媒体查询属性 @media 分别为不同屏幕尺寸的移动设备编写不同尺寸的 css 属性,示例如下所示:

/ <375px /
@media  screen and (max-width:375px) { 
.box {
width: 100%;
}
}
/ >=375px and <450px /
@media  screen and (min-width:375px) and (max-width:450px) { 
.box {
width: 90%;
}
}
/ >=450px /
@media  screen and (min-width:450px) { 
.col{
width: 80%;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

缺点:

页面上所有的元素都得在不同的 @media 中定义一遍不同的尺寸,代价有点高。 如果再多一种屏幕尺寸,就得多写一个 @media 查询块。

# 二、rem 适配方案

rem 是 CSS3 新增的一个相对单位,它是一个相对于页面根元素 html 的 font-size 的一个单位。

假如设置了根元素 html 的 font-size 为 18px,那么 1rem 等于 18px,rem 的大小会随着根元素 html 的 font-size 的改变而改变。rem 方案就是利用了这一点,根据不同的屏幕尺寸,来设置不同的根元素 html 的 font-size 的大小,以此来达到适配不同屏幕尺寸的目的。

目前,除了 IE8 及更早版本外,所有浏览器均已支持 rem。

# 1.使用 flexible

flexible 方案是阿里早期开源的一个移动端适配解决方案,引用 flexible 后,我们在页面上统一使用 rem 来布局。我们创建一个 rem.js 文件:

// 封装一个根据屏幕尺寸自动改变 html 的 font-size 大小的函数

const init = function () {
let clientWidth =
document.documentElement.clientWidth || document.body.clientWidth;
// 设计图尺寸是 750px,这样 *20 之后,1rem 就等于 20px;
const fontSize = (clientWidth / 750 * 20);
document.documentElement.style.fontSize = fontSize + "px";
};

init();

window.addEventListener("resize", init);
export default init;
1
2
3
4
5
6
7
8
9
10
11
12
13
14

在 mian.js 中引入就能够使用了,需要自己手动将 px 转换为 rem

# 2.postcss-pxtorem 插件

参考:通过插件postcss-pxtorem轻松实现px到rem转换,完成移动端适配 (opens new window)

# 三、viewport 适配方案

viewport 是指视窗、视口,即浏览器用来显示网页的那部分区域。

  • window.screen.height 屏幕高度
  • window.innerHeight 网页视口高度
  • document.body.clientHeight body高度

viewport 方案使用 vw/vh 作为样式单位。vw/vh 将 viewport 分成了一百等份,1vw 等于视口 1% 的宽度,1vh 等于视口 1% 的高度。当我们的设计稿宽度是 750px 时,1vw 就等于 7.5px。

  • vw:即Viewport's width,1vw等于window.innerWidth的1%,所以窗口宽度是100vm
  • vh:和vw类似,即Viewport's height,1vh等于window.innerHeihgt的1%
  • vmin:vmin的值是当前vw和vh中较小的值
  • vmax:vmax的值是当前vw和vh中较大的值

# 1.设置 meta 标签

对于手机浏览器浏览页面,常对 viewport 进行如下设置即可:

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

initial-scale:初始缩放比例,即当浏览器第一次加载页面时的缩放比例。maximum-scale:允许浏览者缩放到的最大比例,一般设为1.0。user-scalable:浏览者是否可以手动缩放,yes或no。

# 2.px 自动转换为 vw

使用插件 postcss-px-to-viewport 进行相关配置,就可以帮助我们将 px 自动转化为 vw,提高开发效率。

使用 npm 或 yarn 安装:

npm install postcss-px-to-viewport --save-dev
1

或者

yarn add -D postcss-px-to-viewport
1

webpack 配置:

module.exports = {
  plugins: {
    // ...
    'postcss-px-to-viewport': {
      // options
      unitToConvert: 'px',    // 需要转换的单位,默认为"px"
      viewportWidth: 750,     // 设计稿的视窗宽度
      unitPrecision: 4,       // 单位转换后保留的精度
      propList: ['*', '!font-size'],        // 能转化为 vw 的属性列表
      viewportUnit: 'vw',     // 希望使用的视窗单位
      fontViewportUnit: 'vw', // 字体使用的视窗单位
      selectorBlackList: [],  // 需要忽略的 CSS 选择器,不会转为视窗单位,使用原有的 px 等单位
      minPixelValue: 1,       // 设置最小的转换数值,如果为 1 的话,只有大于 1 的值会被转换
      mediaQuery: false,      // 媒体查询里的单位是否需要转换单位
      replace: true,          // 是否直接更换属性值,而不添加备用属性
      exclude: undefined,     // 忽略某些文件夹下的文件或特定文件,例如 'node_modules' 下的文件
      include: //src//,     // 如果设置了include,那将只有匹配到的文件才会被转换
        landscape: false,       // 是否添加根据 landscapeWidth 生成的媒体查询条件
      landscapeUnit: 'vw',    // 横屏时使用的单位
      landscapeWidth: 1125,   // 横屏时使用的视窗宽度
    },
  },
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

# 3.标注不需要转换的属性

在项目中,如果设计师要求某一场景不做适配,需为固定的宽高或大小,这时我们就需要利用 postcss-px-to-viewport 插件的 ignoring 特性,对不需要转换的属性进行标注,如下所示:

/ example input: /
.box {
/ px-to-viewport-ignore-next /
width: 100px;
padding: 20px;
height: 100px; / px-to-viewport-ignore /
}

/ example output: /
.box {
width: 100px;
padding: 2.6667vw;
height: 100px;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

当然,viewport 适配方案也有一定的缺陷:px 转换成 vw 不一定能完全整除,因此有一定的像素差。