目录
1. rem
2. rem的弊端与优点
3. rem布局前注意点
4. vw
5. vw单位和%单位对比
6. vw布局前注意点
7. vue项目中使用vw
先简单说下rem,官当文档是这样说的:
rem是css中的长度单位,1rem = 根元素html的font-size值。当页面中所有元素都使用rem单位时,你只需要改变根元素 font-size 值,所有元素就会按比例放大或者缩小。因此我们只需要写一小段js代码,根据屏幕宽度改变 html 的 font-size 值,就可以做到弹性布局。这种方法确实便捷,兼容性也很好,是目前非常主流的弹性布局方案。
这里提供一篇完整的、动态的、改变html标签的 font-size 大小的js代码:
(function flexible (window, document) {
var docEl = document.documentElement
var dpr = window.devicePixelRatio || 1
// adjust body font size
function setBodyFontSize () {
if (document.body) {
document.body.style.fontSize = (12 * dpr) + 'px'
}
else {
document.addEventListener('DOMContentLoaded', setBodyFontSize)
}
}
setBodyFontSize();
// set 1rem = viewWidth / 10
function setRemUnit () {
var rem = docEl.clientWidth / 10
docEl.style.fontSize = rem + 'px'
}
setRemUnit()
// reset rem unit on page resize
window.addEventListener('resize', setRemUnit)
window.addEventListener('pageshow', function (e) {
if (e.persisted) {
setRemUnit()
}
})
// detect 0.5px supports
if (dpr >= 2) {
var fakeBody = document.createElement('body')
var testElement = document.createElement('div')
testElement.style.border = '.5px solid transparent'
fakeBody.appendChild(testElement)
docEl.appendChild(fakeBody)
if (testElement.offsetHeight === 1) {
docEl.classList.add('hairlines')
}
docEl.removeChild(fakeBody)
}
}(window, document))
rem布局,需要在html文件头部放入一大段压缩过的js代码很难受,vw则能让你的代码更纯粹!
弊端之一:和根元素font-size值强耦合,系统字体放大或缩小时,会导致布局错乱
弊端之二:html文件头部需插入一段js代码
rem的优点:移动端rem布局比vw主流的原因 兼容性
vw单位兼容性比rem稍差,ios8、安卓4.4及以上才完全支持。
① 视口设置完整
② 设计图在量取的时候可以直接按照1倍图量取
③ 安装插件 px2rem 自动换算,插件中默认html的 font-size 的大小为16px,所以默认是除以16的,如果需要更改,需要进行配置( 如:设计图是375,html标签的font-size的大小为37.5px,此时应该除以37.5 )
我们先来看看 vw vh 单位,w3c的官方解释:
vw:1% of viewport’s width // 视口宽度的 1%
vh:1% of viewport’s height // 视口高度的 1%vmin:vw和vh中最小的那一个
vmax:vw和vh中最大的那一个
viewport 即浏览器可视区域大小
我们可以这样理解 100vw = window.innerwidth, 100vh = window.innerheight
在移动端我们可以认为,100vw 就是屏幕宽度。
百分比%是根据父元素宽度或者高度进行计算,而vw vh固定按照viewport来计算,不会受父元素宽高度影响。
100vw包括了页面滚动条宽度(页面滚动条属于viewport范围内,100vw当然包括了页面滚动条宽度)。但把body或者html设置为width:100%时,是不包括页面滚动条的宽度的。也就是说100vw在有纵向滚动条的情况下,会比100%宽。 那么就会引发一个问题:pc端使用vw单位时,如果页面内容超出一屏长度,会出现了纵向滚动条,同时有元素width:100vw, 则会导致出现条横向滚动条,因为元素(100vw + 滚动条宽度)超出了viewport宽度。(移动端滚动条不占位,所以不会有这个问题)不过pc端一般不需要弹性布局,还是尽量使用width:100%更保险。
① 确定设计稿的宽度(视口的宽度),得到 1vw = 视口的宽度的1%
② vw单位的尺寸 = px / 1vw
例如:
设计稿的宽度是 375px,那么 1vw = 375 / 100 = 3.75px
元素在设计稿中测量出的宽度是 450px
那么就把元素的width设置为 450 / 3.75 = 120vw
③ 能偷懒必须偷懒,咱们可以安装 px2vw 插件自动换算
④ 选择vscode中的设置,搜索 px2vw,设置当前量取的设计稿的尺寸(默认是750)
① 安装 postcss-px-to-viewport 依赖
npm install postcss-px-to-viewport -D
# or
yarn add -D postcss-px-to-viewport
# or
pnpm add -D postcss-px-to-viewport
② 项目根目录下新建 postcss.config.js ,配置如下
// eslint-disable-next-line no-undef
module.exports = {
plugins: {
'postcss-px-to-viewport': {
// 视口宽度375计算vw的值,根据实际情况来修改
viewportWidth: 375
}
}
}
③ 有一个控制台警告可忽略,或者使用 postcss-px-to-viewport-8-plugin 代替当前插件
④ 有了 postcss-px-to-viewport,我们在布局的时候直接写固定px,项目 npm run dev或 npm run build 后会自动将 px 转换成 vw
⑤ 一些特殊的情况,像1px不进行转换,忽略某些文件内的px,可以继续操作 postcss.config.js
module.exports = {
plugins: {
autoprefixer: {},
"postcss-px-to-viewport": {
viewportWidth: 375, //视口的宽度,对应的时设计稿的宽度/2,一般为750,对应iPhone6的宽度
viewportHeight: 667, //视口的高度,对应的是设计稿的高度(也可以不配置)
unitPrecision: 5, //指定‘px’转换为视口单位值的小数位数(很多时候无法整除)小数位为5位
viewportUnit: 'vw', //指定需要转换成的视口单位,建议使用vw(宽度)
selectorBlankList: ['ignore'], //指定不需要转换的类(class类名,使用ignore,在元素的class里加入ignore,则该元素里的px不会进行转化)
minPixelValue: 1, //小于或等于‘1px’不转换为视口单位
mediaQuery: false,//允许在媒体查询中转换为‘px’,使用媒体查询,再对一些东西进行配置
exclude: [/TabBar/] //不需要转化的组件文件名正则,必须是正则表达式
}
}
}