👨一文讲透等比例缩放响应式-px2rem-px2vw

效果

页面宽度为 2000px,里面有个正方形卡片,长宽比为 1:1 ,长宽都是 500px。还有个长方形卡片长宽比为 3:1,长度为 1500px, 宽度为 500px。

等比例缩放

等比例响应式的效果是,当页面宽度变成了原来的 1/2,里面的所有内容尺寸都缩小为 1/2。

当页面的宽度变成了原来的 2 倍,里面的所有尺寸都放大成 2 倍。

要达到这样的效果,可以采用 px 转 rem 的方式,或者 px 转 vw 的方式。

PX TO REM

什么是 Rem?

说到 rem,就离不开 emremem 是 CSS 中常用的两个单位,用于定义元素的尺寸、间距、字体大小等。它们都属于相对单位,与绝对单位(如 px、cm 等)不同。

em 是相对于元素当前字体大小的单位。它的值会根据使用它的元素的字体大小而变化。

  • 如果一个元素的字体大小是 16px,那么 1em 等于 16px
  • 2em 就等于 2 * 16px,也就是 32px

rem 是相对于根元素(即 HTML 元素)的字体大小。无论嵌套多少层,rem 都只基于根元素的字体大小计算。

  • 如果根元素的字体大小是 16px(这是浏览器的默认值),那么 1rem 等于 16px
  • 2rem 就等于 2 * 16px,也就是 32px

em 相对当前元素的字体大小,有继承和累积效应。**rem** 相对根元素的字体大小,没有累积效应,更加一致和可预测。

我们这里使用rem,为的是全局的尺寸都参考同一个标准。当 rem 变大两倍,全局的尺寸也都变大两倍;当 rem 变小两倍,全局的尺寸也都变小两倍。

举个例子:

现在有个这样的样式代码

css 复制代码
html {
  font-size: 16px;
}

.header {
  font-size: 1.5rem; /* 24px, 因为 1.5 * 16px = 24px */
  padding: 1rem; /* 16px */
}

.content {
  font-size: 1rem; /* 16px */
  margin: 2rem; /* 32px, 因为 2 * 16px = 32px */
}

现在假设需要将整体尺寸放大两倍,可以通过调整根元素的字体大小:

css 复制代码
html {
  font-size: 32px; /* 将根元素的字体大小放大到 32px */
}

.header {
  font-size: 1.5rem; /* 48px, 因为 1.5 * 32px = 48px */
  padding: 1rem; /* 32px */
}

.content {
  font-size: 1rem; /* 32px */
  margin: 2rem; /* 64px, 因为 2 * 32px = 64px */
}

通过这种方法,不需要逐个修改每个元素的大小,只需一次调整根元素的字体大小,就能够全局地影响到所有使用 rem 单位的尺寸。这种做法在响应式设计中特别有用,可以方便地调整整体布局和尺寸,以适应不同的屏幕尺寸和设备。

现代化 CSS:postcss-pxtorem

原理

postcss 是一个用 JavaScript 编写的 CSS 处理工具。它允许你使用插件来转换和优化 CSS 代码,从而提升开发效率和代码质量。PostCSS 的强大之处在于它的插件系统,你可以根据需要选择和组合各种插件来满足特定的需求。

简单来说,postcss 就是 css 代码的预处理工具,将 css 代码做一系列的加工处理,并且通过插件扩展各种各样的加工流程。

autoprefixer插件可以给 css 属性加上各种浏览器的前缀,tailwind插件通过读取类名,生成对应的 css 类代码,还有这篇文章要讲的postcss-pxtorem,它的作用是将 css 代码中的 px 单位全部换算成 rem。

postcss-pxtorem 转换单位的换算原理是什么,比如:它怎么知道 16px 要转成 1rem,而不是 2rem 呢?

换算原理很简单,

如果页面根节点(html 节点)的font-size为 16px,说明1rem=16px; 那postcss-pxtorem转换就是下面这样:

javascript 复制代码
8px => 0.5rem
16px => 1rem
24px => 1.5rem
32px => 2rem

如果页面根节点font-size为 32px,那转换过程就是这样:

javascript 复制代码
8px => 0.25rem  // 8px / 32px = 0.25
16px => 0.5rem  // 16px / 32px = 0.5
24px => 0.75rem // 24px / 32px = 0.75
32px => 1rem    // 32px / 32px = 1

很简单吧?

只要单位变成 rem,响应式就好做了,怎么做?动态修改根节点的 font-size 就好了!

当页面宽度变成了原来的 2 倍,就将根节点的 font-size 变成原来的 2 倍,页面中各种 DOM 尺寸自然就变成了原来的 2 倍。

当页面宽度变成了原来的 X 倍,就将根节点的 font-size变成原来的 X 倍,页面中各种 DOM 尺寸自然就变成了原来的 X 倍。

css 代码一旦 build,代码中的数值就不可变了,即原来的 width: 2rem;,无论页面宽度如何变化,代码依旧是width: 2rem;

这就是postcss-pxtorem的基本原理了

配置步骤:

安装依赖:

shell 复制代码
npm i postcss postcss-loader postcss-pxtorem -D

配置 webpack:

javascript 复制代码
export default {
  module:{
    rules:[
      {
        test: /\.css$/,
        use:['style-loader','css-loader','postcss-loader']
      }
    ]
  }
}

配置 postcss.config.js :

javascript 复制代码
module.exports = {
  plugins: [
    'postcss-pxtorem':{
      rootValue: 37.5, // 一般取设计稿的1/10
      unitPrecision: 5, // 转换后的小数位数
      propList: ['*'], // 需要进行转换的属性列表
      selectorBlackList: [], // 不进行转换的选择器列表
      replace: true, // 替换而不是添加 fallback
      mediaQuery: false, // 不转换媒体查询中的 px
      minPixelValue: 0 // 需要进行转换的最小像素值
    }
  ]
}

文件入口:

javascript 复制代码
function setRemUnit() {
	//将页面的十分之一作为1rem。
	const rem = document.body.clientWidth / 10;
	document.querySelector("html")!.style.fontSize = rem + "px";
}

window.addEventListener("resize", setRemUnit);
window.addEventListener("load", setRemUnit);

在配置 postcss-pxtorem时,难点是确定 rootValue到底是多少,以及为什么一般取设计稿宽度的 1/10 作为根节点的 font-size。这里试着将其讲清楚

上文说到postcss-pxtorem在转换单位的时候,是以根节点的font-size作为计算标准的,font-size的值决定了最终得到的数值大小,那么这个 font-size多少合适呢?

理论上任意数值均可!!

我们的目的是做等比例响应式,即页面上的元素尺寸随着页面宽度的变化而变化就行了,至于具体 width1rem 还是 2rem,并没有什么关系

证明:

现在postcss-pxtorem根据font-size: Apx转换 css 代码中的单位(A 为未知数),并且设计稿的宽度为 Bpx(B 为未知数)

现在有 css 代码:

css 复制代码
.header {
  width: Apx;
  height: 2Apx;
  border-radius: 0.1Apx;
}

经过转换后得到:

css 复制代码
.header {
  width: 1rem;
  height: 2rem;
  border-radius: 0.1rem;
}

当页面的宽度为 Bpx,那根节点的字体大小为 Apx,不用修改。

当页面的宽度为 Ypx(Y 为未知数),根节点的字体大小应该是 (Y/B) * A px,现在页面元素的尺寸为原来的(Y/B)

遵循一个原则,页面的宽度变成了多少倍,根节点的字体大小就变成多少倍

证毕

小结

通过上面的证明,可以看到,根节点的大小 Apx 可以为任意值,和设计稿宽度没有任何关系,且依旧保持了等比例的响应式缩放。

那么,上面为什么又说取设计稿的 1/10呢?因为这样做计算简单。

小小证明一下:假设的条件同上,现在令根节点的字体大小为(B/10)px, 当页面宽度为Ypx时,根节点的字体大小应该改成(Y/B) * (B/10)px=>(Y/10)px,即当前页面宽度的 1/10。证毕

PX TO VW

什么是 VW

vwvh 是 CSS 中的视口单位,用于相对于视口(浏览器窗口)尺寸来设置元素的尺寸。它们在响应式设计中非常有用,能够根据视口的大小动态调整元素的尺寸,从而实现更灵活和自适应的布局。

  • vw(viewport width):表示视口宽度的 1%。例如,如果视口宽度是 1000px,那么 1vw 等于 10px。
  • vh(viewport height):表示视口高度的 1%。例如,如果视口高度是 1000px,那么 1vh 等于 10px。

假设视口的宽度是 1200px,高度是 800px:

  • 50vw 等于 600px(即视口宽度的 50%)
  • 50vh 等于 400px(即视口高度的 50%)
css 复制代码
.box {
  width: 50vw; /* 视口宽度的 50% */
  height: 50vh; /* 视口高度的 50% */
  background-color: lightblue;
}

在响应式页面设计中,使用 vwvh 单位可以确保元素根据视口的大小进行调整,从而在不同设备和屏幕尺寸下都能保持良好的布局。设置字体大小时,使用 vw 可以使文本在不同屏幕尺寸下相对稳定。

比如:

css 复制代码
.text {
  font-size: 2vw; /* 字体大小是视口宽度的 2% */
}

现代化 CSS 工具:postcss-pxtoview

postcss-px-to-viewport 也是一个 PostCSS 插件,它可以将 CSS 中的 px 单位自动转换为基于视口单位(vw, vh, vmin, vmax)的单位。这对于实现响应式设计特别有用,因为它可以根据视口大小动态调整元素的尺寸。

原理

假设你有一个 CSS 文件 styles.css,内容如下:

css 复制代码
.header {
  width: 500px;
  height: 250px;
}

.footer {
  width: 100%;
  max-width: 1000px;
  min-height: 50px;
  margin: 0 auto;
}

通过配置 postcss-px-to-viewport,它会将 px 单位转换为 vw 单位。假设页面宽度为 500px,转换后的结果可能如下:

css 复制代码
.header {
  width: 100vw; 
  height: 50vw; 
}

.footer {
  width: 100%;
  max-width: 200vw;
  min-height: 0.1vw;
  margin: 0 auto;
}

单位换算的逻辑是依据当前设置的页面宽度来计算的,当前页面宽度为 500px,那么原先的 500px 自然就转换成 100vw 了,以及 250px,自然就转换成了 50vw

很简单。

配置步骤

安装依赖:

shell 复制代码
npm i postcss postcss-loader postcss-px-to-viewport -D

配置 webpack:

javascript 复制代码
export default {
  module:{
    rules:[
      {
        test: /\.css$/,
        use:['style-loader','css-loader','postcss-loader']
      }
    ]
  }
}

配置 postcss.config.js

javascript 复制代码
module.exports = {
  plugins: {
    'tailwindcss': {},
    'postcss-px-to-viewport': {
      viewportWidth: 500, //设计稿的宽度
      unitPrecision: 5,
      viewportUnit: 'vw',
      selectorBlackList: ['.ignore', '.hairlines'],
      minPixelValue: 1,
      mediaQuery: false,
    }
  }
}

这里viewportWidth的值和设计稿的宽度保持一致就好了。等代码转换的时候,参考标准就是设计稿的宽度了。

转成了 vw 后,就天然支持响应式了。假设一个元素的宽度为 10vw,相当于页面宽度的 10%,当页面的宽度增加了原来的 2 倍,而元素的宽度依旧是整个页面宽度的 10%,相当于也扩大了 2 倍。

这个配置相比于 pxtorem 的方案更简单,也更好懂。

总结

这篇文章讲了页面元素等比例缩放的两个方案: px 转 rem 的方式,以及 px 转 vw 的方式,从概念,原理,然后再讲到配置,深入浅出,通俗易懂。是一篇努力让小白和资深前端都有收获的文章。

欢迎留言评论,以及转发。

相关推荐
m0_7482361123 分钟前
Calcite Web 项目常见问题解决方案
开发语言·前端·rust
Watermelo61736 分钟前
详解js柯里化原理及用法,探究柯里化在Redux Selector 的场景模拟、构建复杂的数据流管道、优化深度嵌套函数中的精妙应用
开发语言·前端·javascript·算法·数据挖掘·数据分析·ecmascript
m0_7482489438 分钟前
HTML5系列(11)-- Web 无障碍开发指南
前端·html·html5
m0_748235611 小时前
从零开始学前端之HTML(三)
前端·html
一个处女座的程序猿O(∩_∩)O3 小时前
小型 Vue 项目,该不该用 Pinia 、Vuex呢?
前端·javascript·vue.js
hackeroink6 小时前
【2024版】最新推荐好用的XSS漏洞扫描利用工具_xss扫描工具
前端·xss
迷雾漫步者7 小时前
Flutter组件————FloatingActionButton
前端·flutter·dart
向前看-8 小时前
验证码机制
前端·后端
燃先生._.9 小时前
Day-03 Vue(生命周期、生命周期钩子八个函数、工程化开发和脚手架、组件化开发、根组件、局部注册和全局注册的步骤)
前端·javascript·vue.js