> 文章列表 > 移动端布局rem与vw的区别

移动端布局rem与vw的区别

移动端布局rem与vw的区别

目录

1. rem 

2. rem的弊端与优点

3. rem布局前注意点

4. vw

5. vw单位和%单位对比

6. vw布局前注意点

7. vue项目中使用vw


1. rem 

先简单说下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.documentElementvar dpr = window.devicePixelRatio || 1// adjust body font sizefunction setBodyFontSize () {if (document.body) {document.body.style.fontSize = (12 * dpr) + 'px'}else {document.addEventListener('DOMContentLoaded', setBodyFontSize)}}setBodyFontSize();// set 1rem = viewWidth / 10function setRemUnit () {var rem = docEl.clientWidth / 10docEl.style.fontSize = rem + 'px'}setRemUnit()// reset rem unit on page resizewindow.addEventListener('resize', setRemUnit)window.addEventListener('pageshow', function (e) {if (e.persisted) {setRemUnit()}})// detect 0.5px supportsif (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))

2. rem的弊端与优点

rem布局,需要在html文件头部放入一大段压缩过的js代码很难受,vw则能让你的代码更纯粹!

弊端之一:和根元素font-size值强耦合,系统字体放大或缩小时,会导致布局错乱

弊端之二:html文件头部需插入一段js代码

rem的优点:移动端rem布局比vw主流的原因 兼容性

vw单位兼容性比rem稍差,ios8、安卓4.4及以上才完全支持。

3. rem布局前注意点

① 视口设置完整

<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0" />

② 设计图在量取的时候可以直接按照1倍图量取

③ 安装插件 px2rem 自动换算,插件中默认html的 font-size 的大小为16px,所以默认是除以16的,如果需要更改,需要进行配置( 如:设计图是375,html标签的font-size的大小为37.5px,此时应该除以37.5 )

4. vw

我们先来看看 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 就是屏幕宽度。

5. vw单位和%单位对比

百分比%是根据父元素宽度或者高度进行计算,而vw vh固定按照viewport来计算,不会受父元素宽高度影响。
100vw包括了页面滚动条宽度(页面滚动条属于viewport范围内,100vw当然包括了页面滚动条宽度)。但把body或者html设置为width:100%时,是不包括页面滚动条的宽度的。也就是说100vw在有纵向滚动条的情况下,会比100%宽。 那么就会引发一个问题:pc端使用vw单位时,如果页面内容超出一屏长度,会出现了纵向滚动条,同时有元素width:100vw, 则会导致出现条横向滚动条,因为元素(100vw + 滚动条宽度)超出了viewport宽度。(移动端滚动条不占位,所以不会有这个问题)不过pc端一般不需要弹性布局,还是尽量使用width:100%更保险。

6. vw布局前注意点

① 确定设计稿的宽度(视口的宽度),得到 1vw = 视口的宽度的1%

② vw单位的尺寸 = px / 1vw

例如:

设计稿的宽度是 375px,那么 1vw = 375 / 100 = 3.75px

元素在设计稿中测量出的宽度是 450px

那么就把元素的width设置为 450 / 3.75 = 120vw

③ 能偷懒必须偷懒,咱们可以安装 px2vw 插件自动换算

④  选择vscode中的设置,搜索 px2vw,设置当前量取的设计稿的尺寸(默认是750)

7. vue项目中使用vw

① 安装 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/]  //不需要转化的组件文件名正则,必须是正则表达式}}
}