移动端设计稿一般是750px,如果没有用taro或者uniapp这类的框架,就需要自己来进行css的适配。
rem是相对于根元素html字体大小的一个css单位,默认情况下html的font-size=16px,所以1rem = 16px。可以动态设置html的字体大小,比如设置html的font-size=100px,那么1rem=100px。重点就是动态设置html字体大小。
先在html的head标签中加一个meat标签
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
意思是让当前视口的宽度等于设备的宽度,同时不允许用户手动缩放。
如果只是简单的一两个页面,html直接梭了,甚至都不需要用react、vue,那么可以继续在head中引入这段js
<script>
function setSize() {
var baseWidth = 750 // 设计稿尺寸
var clientWidth = document.documentElement.clientWidth
if (clientWidth >= 750) {
clientWidth = 750
}
var fontSize = (clientWidth / baseWidth) * 100 // 乘以100是为了方便计算
window.document.documentElement.style.fontSize = fontSize + 'px'
}
setSize()
window.addEventListener('resize', setSize)
</script>
写样式的时候,100px*100px的宽高可以写成width:1rem;height:1rem
,50px*50px的宽高可以写成width:0.5rem;height:0.5rem
,其实就是设计稿里的尺寸/100
如果是正常开发一个项目,这么去换算肯定麻烦,肯定是需要自动换算,插件postcss-pxtorem
可以满足这个需求,这时候需要加入另一段js。用上面一段也没什么大问题,核心就是设计稿尺寸下的字体大小,上面的js在iPhone6下fontSize是50px,那么插件rootValue值要设置成50,下面这段js在iPhone6下fontSize是16px,那么插件rootValue值要设置成16
<script>
function setSize() {
var baseFontSize = 16; // 这个值要和下面插件的rootValue值一样
var baseWidth = 375; // 设计稿尺寸
var clientWidth = document.documentElement.clientWidth;
if (clientWidth > 750) {
clientWidth = 750;
}
document.documentElement.style.fontSize =
baseFontSize * (clientWidth / baseWidth) + "px";
}
setSize();
window.addEventListener("resize", setSize);
</script>
1、安装
使用postcss-pxtorem
前提是需要安装 postcss postcss-loader
npm i postcss postcss-loader postcss-pxtorem -D
2、webpack配置
或者新建一个 postcss.config.js 文件也行(.json,.yaml格式的文件都行,看个人习惯)
// 引入插件
const Pxtorem = require('postcss-pxtorem');
module.export = {
module:{
rules:[
{
test: /\.css$/i,
use: [
"style-loader",
"css-loader",
{
loader: "postcss-loader",
options: {
postcssOptions: {
plugins: [
Pxtorem({
rootValue: 16,
unitPrecision: 5,
propList: ['*'],
selectorBlackList: [],
replace: true,
mediaQuery: false,
minPixelValue: 0,
// exclude: /node_modules/i
})
],
},
},
},
],
},
]
}
}
postcss-pxtorem
的默认配置如下
{
rootValue: 16,
unitPrecision: 5,
propList: ['font', 'font-size', 'line-height', 'letter-spacing'],
selectorBlackList: [],
replace: true,
mediaQuery: false,
minPixelValue: 0,
exclude: /node_modules/i
}
rootValue
:根结点的字体大小,默认16,可以设置一个具体的数值,或者可以是一个函数,返回一个数值。如果用到了UI库,可能UI库是按照375,设计稿是750,就可以通过函数来设置rootValue。该函数有一个参数,是一个对象,可以通过file
字段来判断是自己写的样式还是UI库的样式,file
是当前文件的路径。function ({file}) { return file.indexOf('exclude') !== -1; }
unitPrecision
:保留几位小数propList
:一个数组。表示哪些属性能转化成rem
height
,width
background-position-y
和min-height
、max-height
selectorBlackList
:一个数组,要忽略的选择器,保留为px。
.body-main
body
但是不会匹配 .body
replace
:Boolean,是否替换包含rem的规则,而不是添加回退mediaQuery
:Boolean,是否允许在媒体查询中转换pxminPixelValue
:数值,设置要替换的最小像素值exclude
:(String, Regexp, Function) 要忽略并保留为px的文件路径
function (file) { return file.indexOf('exclude') !== -1; }
如果只是单个属性需要忽略,最简单的是大写PX
// `px` 会转成 `rem`
.convert {
font-size: 16px; // 会被转成rem
}
// `Px` or `PX` 会被忽略,但是在浏览器里面仍然可以用
.ignore {
border: 1Px solid; // ignored
border-width: 2PX; // ignored
}
vw和vh是浏览器视口(viewport)的单位,简单理解就是1vw是屏幕宽度的1%,1vh是屏幕高度的1%,此外还有vmin:vw和vh中较小的那个,vmain:vw和vh中较大的那个。
vw也不用自己手动去换算,现在浏览器都支持vw、vh,可以用postcss-px-to-viewport
插件进行转换,和rem的插件用法类似(本身也是受postcss-pxtorem
启发)
1、安装
npm i postcss postcss-loader postcss-px-to-viewport -D
2、webpack配置
// 引入插件
const postcssPxToViewport = require("postcss-px-to-viewport");
module.export = {
module:{
rules:[
{
test: /\.css$/i,
use: [
"style-loader",
"css-loader",
{
loader: "postcss-loader",
options: {
postcssOptions: {
plugins: [
postcssPxToViewport({
viewportWidth: 320, // 设计稿宽度
unitPrecision: 5, // px转换后的小数保留位数
minPixelValue: 1, // 小于多少像素不转换
selectorBlackList: ["ignore-"], // 有ignore-* 的类名不会被转换
}),
],
},
},
},
],
},
]
}
}
postcss-px-to-viewport
的默认配置如下
{
unitToConvert: 'px',
viewportWidth: 320,
unitPrecision: 5,
propList: ['*'],
viewportUnit: 'vw',
fontViewportUnit: 'vw',
selectorBlackList: [],
minPixelValue: 1,
mediaQuery: false,
replace: true,
exclude: undefined,
include: undefined,
landscape: false,
landscapeUnit: 'vw',
landscapeWidth: 568
}
unitToConvert
(String) 需要转换的单位,默认为"px"viewportWidth
(Number) 设计稿的视口宽度unitPrecision
(Number) 单位转换后保留的精度propList
(Array) 能转化为vw的属性列表
background-position-y
)letter-spacing
font-size
以及font-weight
等属性fontViewportUnit
(String) 字体使用的视口单位selectorBlackList
(Array) 需要忽略的CSS选择器,不会转为视口单位,使用原有的px等单位。
.body-class
就会被忽略body
会被忽略,而 .body
不会.minPixelValue
(Number) 设置最小的转换数值,如果为1的话,只有大于1的值会被转换mediaQuery
(Boolean) 媒体查询里的单位是否需要转换单位replace
(Boolean) 是否直接更换属性值,而不添加备用属性exclude
(Array or Regexp) 忽略某些文件夹下的文件或特定文件,例如 ‘node_modules’ 下的文件
include
(Array or Regexp) 如果设置了include,那将只有匹配到的文件才会被转换,例如只转换 ‘src/mobile’ 下的文件 (include: /\/src\/mobile\//
)
landscape
(Boolean) 是否添加根据 landscapeWidth 生成的媒体查询条件 @media (orientation: landscape)landscapeUnit
(String) 横屏时使用的单位landscapeWidth
(Number) 横屏时使用的视口宽度exclude和include是可以一起设置的,将取两者规则的交集。
个人感觉移动端适配这两种方案都行,rem算是大家用的比较久的,vw是后发展的方案