- 作者:老汪软件技巧
- 发表时间:2024-12-02 11:08
- 浏览量:
前言
rem(root em,根em)是 CSS3 新增的一个相对单位, 表示相对于根元素(html)的字体大小。这个单位与 em 的区别在于使用 rem 相对的是 HTML根元素。
这个单位可谓集相对大小和绝对大小的优点于一身,通过它既可以做到只修改根元素就成比例地调整所有尺寸大小,又可以避免逐层复合的连锁反应。目前,除了IE8及更早版本外,所有浏览器均已支持rem。
因此,使用rem单位可以让开发者更容易地实现响应式设计,因为我们只需要关注根元素的font-size。
举个简单的例子:设置字体大小和边距
html>
<html>
<head>
<style>
/* 设置根元素的字体大小 */
html {
font-size: 16px;
}
/* 使用rem单位设置一个元素的字体大小 */
h1 {
font-size: 2rem;
}
/* 使用rem单位设置一个元素的边距 */
p {
margin-bottom: 1rem;
}
style>
head>
<body>
<h1>标题h1>
<p>内容p>
<p>内容p>
body>
html>
注意:使用声明为标准模式,防止浏览器在渲染文档时,切换到我们称为“怪异模式”的渲染模式,在怪异模式下样式继承会出现问题
在这个示例中,我们设置了根元素(html)的字体大小为 16px。然后,我们使用rem单位设置了标题(h1)的字体大小为 2rem,这等于 32px(2 * 16)。
我们还为段落(p)设置了 1rem 的底部边距,等于 16px(1 * 16)。我们想让整个页面等比变化,只需要更改根元素的font-size 属性即可,如
html {
font-size: 20px;
}
基于此,我们在页面初始化的时候,初始化根元素的 font-size 值,监听 onresize 事件在窗口大小变化时,根据比例动态计算出根元素的 font-size 值,那么就能确保网站在不同设备上都能呈现出最佳的效果。
const getScreenWidth = () => window.innerWidth || window.screen.availWidth || window.screen.width;
const setRootFontSize = () => {
const designWidth = 375; // 设计稿宽度
const minWidth = 360;
const maxWidth = 480;
const baseFontSize = 16;
const windowWidth = getScreenWidth();
let adaptiveWidth;
if (windowWidth <= minWidth) {
adaptiveWidth = minWidth;
} else if (windowWidth >= maxWidth) {
adaptiveWidth = maxWidth;

} else {
adaptiveWidth = windowWidth;
}
const fontSize = baseFontSize * (adaptiveWidth / designWidth);
// 保留3位小数
document.documentElement.style.fontSize = `${toFixedBySelf(fontSize, 3)}px`;
};
// 初始化根元素字体大小
setRootFontSize();
// 改变窗口时重新设置
window.onresize = throttle(() => {
setRootFontSize();
}, 200);
我们可以借助 webpack 工具 postcss-pxtorem 来完成单位的自动转化,因此开发时正常使用px即可。
在项目根目录添加 postcss.config.ts文件
module.exports = {
plugins: {
'postcss-pxtorem': {
rootValue: 16, // 基准值
unitPrecision: 5, // 转换后的 rem 值保留的小数位数
propList: ['*'],
selectorBlackList: [],
replace: true, // 是否直接替换属性值,而不是添加备用属性。
mediaQuery: false, // 是否允许在媒体查询中转换 px。
minPixelValue: 0, // 设置要替换的最小像素值。
},
},
};
某些场景下,我们可能不需要进行单位的转化,因此 postcss-pxtorem 配置项为我们提供了可以避免px转rem的实现方法:
1、propList:允许从 px 更改为 rem 的属性列表
propList: ['*', '!border*'] // 如:不转换任何包含 "border" 的属性
2、selectorBlackList:选择器黑名单,如果选择器中包含这些字符串,则不转换对应的 px
selectorBlackList: ['html', '.no-rem'] // 如:不转换 "html" 标签和包含 "no-rem" 类的选择器
注意:在内联样式中编写样式属性时,我们需要手动将单位转换为rem
function pxToRem(value) {
return `${value / 16}rem`;
}
注意,打包时 postcss-pxtorem 只会将样式文件中的单位进行自动转换,而我们写在内联样式不会进行处理,故需要手动进行单位的转换。
总结
优点:
缺点: