效果
页面宽度为 2000px,里面有个正方形卡片,长宽比为 1:1 ,长宽都是 500px。还有个长方形卡片长宽比为 3:1,长度为 1500px, 宽度为 500px。
等比例缩放
等比例响应式的效果是,当页面宽度变成了原来的 1/2,里面的所有内容尺寸都缩小为 1/2。
当页面的宽度变成了原来的 2 倍,里面的所有尺寸都放大成 2 倍。
要达到这样的效果,可以采用 px 转 rem 的方式,或者 px 转 vw 的方式。
PX TO REM
什么是 Rem?
说到 rem
,就离不开 em
。rem
和 em
是 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
多少合适呢?
理论上任意数值均可!!
我们的目的是做等比例响应式,即页面上的元素尺寸随着页面宽度的变化而变化就行了,至于具体 width
是 1rem
还是 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
vw
和 vh
是 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;
}
在响应式页面设计中,使用 vw
和 vh
单位可以确保元素根据视口的大小进行调整,从而在不同设备和屏幕尺寸下都能保持良好的布局。设置字体大小时,使用 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 的方式,从概念,原理,然后再讲到配置,深入浅出,通俗易懂。是一篇努力让小白和资深前端都有收获的文章。
欢迎留言评论,以及转发。