信息发布→ 登录 注册 退出

css 使用 rem 和 em 单位_实现灵活的响应式布局

发布时间:2026-01-12

点击量:
rem是相对于根元素font-size的单位,1rem默认为16px,通过动态设置document.documentElement.style.fontSize实现响应式;em则相对于父元素font-size,易因嵌套连乘失控,适合局部适配;clamp()提供无JS、无FOUC的响应式方案,但需考虑兼容性。

rem 是相对于根元素 font-size 的单位

浏览器默认根元素 font-size 是 16px,所以 1rem 默认等于 16px。只要动态改 document.documentElement.style.fontSize,所有用 rem 的尺寸就同步缩放——这是实现响应式字体和间距的核心机制。

常见做法是在 中插入一段 JS,根据屏幕宽度按比例设置根字号,比如:

function setRootFontSize() {
  const width = document.documentElement.clientWidth;
  const base = 375; // 设计稿宽度
  const scale = width / base;
  document.documentElement.style.fontSize = `${scale * 16}px`;
}
setRootFontSize();
window.addEventListener('resize', setRootFontSize);

注意:这段逻辑必须在 DOM 加载前或早期执行,否则页面可能闪动;如果用 Webpack/Vite,建议封装为自执行函数并确保早于 CSS 加载。

em 是相对于父元素 font-size 的单位

em 的值取决于**直接父元素**的 font-size,逐层继承、容易嵌套失控。比如父元素是 1.2em(即 19.2px),子元素写 1.2em 就变成 19.2 × 1.2 ≈ 23px,再下一层继续乘——这不是“缩放”,而是“连乘”,不适合全局响应式控制。

em 在局部场景仍有价值:

  • 按钮内边距跟随文字大小变化:padding: 0.5em 1em;
  • 图标尺寸与文字对齐:font-size: 1.2em; 配合 line-height: 1;
  • 伪元素尺寸适配文字:::before { font-size: 0.8em; }

别用 em 控制布局容器宽高,尤其在 flex/grid 容器里,会因父级字号变动导致意料外的缩放链。

rem + viewport 缩放容易踩的坑

很多方案同时设置 和动态 rem,但 iOS Safari 在横竖屏切换时可能触发双倍缩放,导致 clientWidth 计算失真。

规避方法:

  • 避免在 viewport 中写 maximum-scaleuser-scalable=no,它们会干扰系统缩放逻辑
  • window.innerWidth 替代 document.documentElement.clientWidth 做计算基准(更稳定)
  • 监听 orientationchange 事件,而非仅靠 resize
  • 对 PC 端做降级:媒体查询判断 min-width: 768px 后固定根字号为 16px,防止桌面端误缩放

现代项目建议用 clamp() 替代纯 rem 方案

CSS clamp() 能在最小值、首选值、最大值之间平滑过渡,比 JS 动态改根字号更轻量、无 FOUC、支持服务端渲染:

p {
  font-size: clamp(14px, 2.5vw, 18px);
}
.card {
  padding: clamp(12px, 3vw, 24px);
}

但要注意兼容性:clamp() 在 Safari 13.1+、Chrome 88+、Firefox 79+ 支持;老版本需 fallback 到 rem 或媒体查询。

真正复杂的地方不在单位本身,而在「何时该用 rem、何时该用 em、何时该放弃它们直接上视口单位或 clamp」——这取决于你是否需要 JavaScript 参与控制、是否要兼顾 SSR、以及设计系统对缩放一致性的要求程度。

标签:# css  # javascript  # java  # html  # js  # vite  # 伪元素  # 浏览器  # safari  # ios  # win  
在线客服
服务热线

服务热线

4008888355

微信咨询
二维码
返回顶部
×二维码

截屏,微信识别二维码

打开微信

微信号已复制,请打开微信添加咨询详情!