一些常见的移动端适配方案
# 前言
移动端设备的尺寸很多,而 UI 设计稿一般只会基于一个尺寸(一般是 375px 或 750px )进行设计。
目前移动端适配方案有多种,本文将介绍一些具有代表性的适配方案。
# 媒体查询 @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%;
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
缺点:
1.页面上所有的元素都得在不同的@media
中定义一遍不同的尺寸,代价有点高。
2.如果再多一种屏幕尺寸,就得多写一个@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;
2
3
4
5
6
7
8
9
10
11
12
13
在 mian.js
中引入就能够使用了,需要自己手动将 px
转换为 rem
# 2. postcss-pxtorem 插件
参考:通过插件postcss-pxtorem轻松实现px到rem转换,完成移动端适配 (opens new window)
# viewport 适配方案
viewport
是指视窗、视口,即浏览器用来显示网页的那部分区域。
viewport
方案使用 vw/vh
作为样式单位。vw/vh
将 viewport
分成了一百等份,1vw
等于视口 1%
的宽度,1vh
等于视口 1%
的高度。当我们的设计稿宽度是 750px
时,1vw
就等于 7.5px
。
# 1. 设置 meta 标签
对于手机浏览器浏览页面,常对 viewport 进行如下设置即可:
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=yes">
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
或者
yarn add -D postcss-px-to-viewport
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, // 横屏时使用的视窗宽度
},
},
};
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;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
当然,viewport
适配方案也有一定的缺陷:px
转换成 vw
不一定能完全整除,因此有一定的像素差。
# 最后
目前比较推荐的移动适配方案是 rem&vw
,了解其中的适配原理对于前端而言是非常重要的,相关问题也经常出现在面试题中。熟练使用插件也能给我们的工作带来很大的帮助。