简介
最常见的移动端适配分为两种,基于rem
、基于viewport
目前应用的单位最多还是rem
移动端适配都需要在html
页面中定义meta
,定义用户通过手指放大缩小无效,页面比例始终保持为1:1
<meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=0,minimum-scale=1.0,maximum=scale=1.0">
基于 rem
-
rem
是一个单位,这个单位是基于html
标签的font-size
值计算的 -
比如设置了
html
标签的font-size
值为16px
。那么对应的2rem
计算出来实际上就是32px
-
使用
rem
适配首先需要设置html
标签的font-size
值,可以直接在样式中设置,或者编写js
设置,或者使用插件(比如:amfe-flexible
) -
然后再代码中用到尺寸的地方使用
rem
代替px
作为单位 -
也可以在代码中使用
px
作为单位,借助webpack
的一些插件实现将px
自动转换成rem
。这类插件比如:postcss-pxtorem
、postcss-px2rem
、px2rem-loader
备注:
lib-flexible
方案已经不推荐使用
基于 viewport
viewport
单位已经越来越受到众多浏览器的支持。可以使用viewport
单位做移动端的适配
vw
:屏幕宽度单位,100vw
就是整个屏幕宽度vh
:屏幕高度单位,100vh
就是整个屏幕高度
rem 适配之 手动计算值
- 这里直接使用
vw
设置html
的font-size
值- 手动计算效果图中的像素大小,对应于代码中是多少
rem
- 代码中的单位为
rem
- 修改公共样式文件,设置
html
的font-size
值。比如:src/assets/less/base.less
html,body{ font-size: calc(100vw/7.5); }
// 这里以效果图 750px 为例
// 750px 对应 100vw
// 为了方便,我们将 750px 设置成 7.5rem;也就是:效果图中的像素大小 / 100
// 1rem 就是 100vw / 7.5
// 这样效果图上面,比如宽度是 320px,代码中就写 3.2rem
// 同理如果效果图大小是 1024px,那么就设置 font-size: calc(100vw/10.24)
- 在代码中,单位使用
rem
。大小为效果图中大小 / 100
rem 适配之设置 font-size
- 使用
rem
首先需要设置html
的font-size
值。- 可以自己写
js
或者使用插件(如:amfe-flexible
)- 这里我们将屏幕宽度设置成
10rem
来计算,方便后面与postcss-pxtorem
等集成
js设置
- 在
src/utils/
目录下添加rem.js
文件
// 设置 rem 函数
function setRem () {
const htmlWidth = document.documentElement.clientWidth || document.body.clientWidth
// 得到 html 的 Dom 元素
const htmlDom = document.getElementsByTagName('html')[0]
// 设置根元素字体大小
htmlDom.style.fontSize = htmlWidth / 10 + 'px'
}
// 初始化
setRem()
// 改变窗口大小时重新设置 rem
window.onresize = function () {
setRem()
}
- 修改
src/main.js
文件,引入该文件
// ...
import './utils/rem'
// ...
amfe-flexible
- 安装
amfe-flexible
npm i amfe-flexible --save
- 修改
src/main.js
文件,引入amfe-flexible
// ...
import 'amfe-flexible'
// ...
备注:
- 使用此插件可以自动动态给
html
标签设置font-size
值- 比如设备尺寸
414*736
,在竖屏情况下font-size: 41.4px
;横屏情况下font-size: 73.6px
- 即:
font-size
的值被设置成了设备宽 / 10
- 屏幕宽度就是
10rem
- 支持
0.5px
rem 适配之 postcss-pxtorem
- 首先需要设置
html
的font-size
值。在上一节中已经介绍- 可以使用
postcss-pxtorem
,将px
单位自动转换成rem
单位- 效果图中尺寸多大,代码中就写多大。单位
px
使用
- 安装
postcss-pxtorem
npm i postcss-pxtorem --save-dev
- 在
vue-cli2.x
的项目中使用:修改.postcssrc.js
文件
// ...
module.exports = {
"plugins": {
// ...
// to edit target browsers: use "browserslist" field in package.json
"autoprefixer": {},
'postcss-pxtorem': {
rootValue: 75, // 换算的基数。这里填写 '效果图尺寸 / 10' 这样的话屏幕尺寸正好对应 10rem
// 忽略转换正则匹配项。插件会转化所有的样式的px。比如引入了三方UI,也会被转化。目前我使用 selectorBlackList 字段,来过滤
// 如果个别地方不想转化px。可以简单的使用大写的 PX 或 Px。
// selectorBlackList : ['weui','mu'],
propList: ['*']
}
}
}
- 在
vue-cli3.x
的项目中使用:如果有postcss.config.js
,修改此文件
module.exports = {
plugins: {
autoprefixer: {},
'postcss-pxtorem': {
rootValue: 75, // 换算的基数。这里填写 '效果图尺寸 / 10' 这样的话屏幕尺寸正好对应 10rem
propList: ['*']
}
}
}
- 在
vue-cli3.x
的项目中使用:如果没有postcss.config.js
,修改vue.config.js
文件
const autoprefixer = require('autoprefixer');
const pxtorem = require('postcss-pxtorem');
// ...
module.exports = {
// ...
css: {
loaderOptions: {
postcss: {
plugins: [
autoprefixer(),
pxtorem({
rootValue: 75, // 结果为:设计稿元素尺寸 / 75,比如元素宽 750px,最终页面会换算成 10rem
propList: ['*']
})
]
}
}
}
};
参数
config = {
rootValue: 16, // (Number) 根元素的font-size。这里可以理解成基数
unitPrecision: 5, // (Number) 指定`px`转换为视窗单位值的小数位数,默认是5
propList: ['font', 'font-size', 'line-height', 'letter-spacing'], // (Array) 指定可以转换的css属性,默认是['*'],代表全部属性进行转换
selectorBlackList: [], // (Array) 指定不转换为视窗单位的类,保留px,值为string或正则regexp,建议定义一至两个通用的类名
replace: true, // (Boolean) replaces rules containing vw instead of adding fallbacks
mediaQuery: false, // (Boolean) 是否在媒体查询时也转换px,默认false
minPixelValue: 0 // (Number) 默认值1,小于或等于`1px`不转换为视窗单位
}
rem 适配之 postcss-px2rem
- 用法与
postcss-pxtorem
基本相同 postcss-pxtorem
中rootValue
,对应postcss-px2rem
中的remUnit
rem 适配之 px2rem-loader
- 首先需要设置
html
的font-size
值。在上一节中已经介绍- 可以使用
px2rem-loader
,将px
单位自动转换成rem
单位- 效果图中尺寸多大,代码中就写多大。单位
px
使用
- 安装
px2rem-loader
npm i px2rem-loader --save-dev
- 在
vue-cli2.x
的项目中使用:修改build/utils.js
文件
// ...
exports.cssLoaders = function (options) {
// ...
// 添加 px2remLoader
const px2remLoader = {
loader: 'px2rem-loader',
options: {
// 换算的基数。这里填写 '效果图尺寸 / 10' 这样的话屏幕尺寸正好对应 10rem
// 如果个别地方不想转化px。可以简单的使用大写的 PX 或 Px。
remUnit: 75
}
}
// generate loader string to be used with extract text plugin
function generateLoaders (loader, loaderOptions) {
// const loaders = options.usePostCSS ? [cssLoader, postcssLoader] : [cssLoader]
// 注释掉上面一行,添加下面一行
const loaders = options.usePostCSS ? [cssLoader, postcssLoader, px2remLoader] : [cssLoader, px2remLoader]
// ...
}
// ...
}
// ...
- 在
vue-cli3.x
的项目中使用:修改vue.config.js
文件
// ...
module.exports = {
// ...
chainWebpack: config => {
config.module
// // css
// .rule('css')
// .test(/\.css$/)
// .oneOf('vue')
// .resourceQuery(/\?vue/)
// .use('px2rem')
// .loader('px2rem-loader')
// .options({
// // 结果为:设计稿元素尺寸 / 75,比如元素宽 750px,最终页面会换算成 10rem
// remUnit: 75
// })
// 如果使用了 less
.rule('less')
.test(/\.less$/)
.oneOf('vue')
.use('px2rem-loader')
.loader('px2rem-loader')
.before('postcss-loader') // this makes it work.
.options({ remUnit: 75 })
.end()
}
};
参数
config = {
baseDpr: 2, // (Number) 设备像素比,默认为 2
remUnit: 75, // (Number) rem基数,默认 75
remPrecision: 6, // (Number) 指定'px'转换为视窗单位值的小数位数,默认是 6
forcePxComment: 'px', // (String) force px comment (default: 'px')
keepComment: 'no' // (String) no transform value comment (default: 'no')
}
viewport 适配之 postcss-px-to-viewport
- 可以使用
postcss-px-to-viewport
,将px
单位自动转换成viewport
单位viewportWidth
大小设置成效果图尺寸,这样效果图中尺寸多大,代码中就写多大。单位px
使用
- 安装
postcss-px-to-viewport
npm i postcss-px-to-viewport --save-dev
- 在
vue-cli2.x
的项目中使用:修改.postcssrc.js
文件
// ...
module.exports = {
"plugins": {
// ...
// to edit target browsers: use "browserslist" field in package.json
"autoprefixer": {},
'postcss-px-to-viewport': {
viewportWidth: 750, // 视窗的宽度,对应的是我们设计稿的宽度,一般是750
viewportHeight: 1334, // 视窗的高度,根据750设备的宽度来指定,一般指定1334,也可以不配置
unitPrecision: 3, // 指定`px`转换为视窗单位值的小数位数
viewportUnit: "vw", //指定需要转换成的视窗单位,建议使用vw
selectorBlackList: ['.ignore'],// 指定不转换为视窗单位的类,可以自定义,可以无限添加,建议定义一至两个通用的类名
minPixelValue: 1, // 小于或等于`1px`不转换为视窗单位,你也可以设置为你想要的值
mediaQuery: false // 允许在媒体查询中转换`px`
}
}
}
- 在
vue-cli3.x
的项目中使用:如果有postcss.config.js
,修改此文件
// ...
module.exports = {
plugins: {
// ...
autoprefixer: {},
'postcss-px-to-viewport': {
viewportWidth: 750
}
}
}
- 在
vue-cli3.x
的项目中使用:如果没有postcss.config.js
,修改vue.config.js
文件
const autoprefixer = require('autoprefixer');
const pxtoviewport = require('postcss-px-to-viewport');
// ...
module.exports = {
// ...
css: {
loaderOptions: {
postcss: {
plugins: [
autoprefixer(),
pxtoviewport({
viewportWidth: 750
})
]
}
}
}
};
参数
viewportWidth
就是设计稿的宽度
比如:设计稿宽度750px
,设置的viewportWidth
值也是750px
那么对应的100vw
就是750px
,1vw
也就是7.5px
编写代码时,设计稿上面是多少像素,代码就写多少px
代码中的300px
转换后也就是300 / 7.5 = 40vw
config = {
unitToConvert: 'px' // (String) 要转换的单位,默认是'px'
viewportWidth: 320, // (Number) viewport的宽度,默认是320,可根据设计稿来,750的设计稿就写750
unitPrecision: 5, // (Number) 指定`px`转换为视窗单位值的小数位数,默认是5
propList: ['*'], // (Array) 指定可以转换的css属性,默认是['*'],代表全部属性进行转换
viewportUnit: 'vw', // (String)指定需要转换成的视窗单位,默认vw
fontViewportUnit: 'vw', // (String)指定字体需要转换成的视窗单位,默认vw
selectorBlackList: [], // (Array) 指定不转换为视窗单位的类,保留px,值为string或正则regexp,建议定义一至两个通用的类名
minPixelValue: 1, // (Number) 默认值1,小于或等于`1px`不转换为视窗单位
mediaQuery: false, // (Boolean) 是否在媒体查询时也转换px,默认false
replace: true, // (Boolean) replaces rules containing vw instead of adding fallbacks
exclude: [], // (Array or Regexp) 设置忽略文件,如node_modules
landscape: false, // (Boolean) @media (orientation: landscape) with values converted via landscapeWidth
landscapeUnit: 'vw', // (String) Expected unit for landscape option
landscapeWidth: 568 // (Number) Viewport width for landscape orientation.
}
问题
-
@keyframes
和media
查询里的px
默认是不转化的,设置mediaQuery:true
则媒体查询里也会转换px
-
@keyframes
可以暂时手动填写vw
单位的转化结果
发表评论