rem和em在Vue组件里到底该怎么用才不会乱?

司徒爱香 阅读 28

我在做移动端页面,想用rem做响应式布局,但发现组件里的字体大小有时候特别奇怪,明明根字体设了,子元素用em就失控了。比如下面这个按钮:

<template>
  <div class="container">
    <button class="btn">点击我</button>
  </div>
</template>

<style scoped>
.container {
  font-size: 16px;
}
.btn {
  font-size: 1.2em; /* 这里预期是19.2px,但实际变大了好多 */
}
</style>

是不是因为em是相对于父元素字体,而rem才是相对于html根字体?那在Vue组件里到底该优先用哪个?

我来解答 赞 1 收藏
二维码
手机扫码查看
2 条解答
诸葛惠泽
这个问题其实不在Vue本身,而是em和rem的机制问题。

先说你的代码为什么出问题。em是相对于最近的可继承font-size的父元素,不是相对于组件里写的那个人。你这段代码如果单独跑,1.2em确实应该是19.2px。但实际项目中,你很可能把组件嵌入到了其他父容器里,比如外层有个设置了font-size: 20px的div,那btn的1.2em就变成24px了,这就是你说的"变大好多"。

根本原因是em的相对性太不可控,它会一级一级往上找父元素的font-size,组件被复用到不同地方时就容易翻车。

我的建议是分场景用:

全局性的、跟页面布局相关的尺寸用rem,比如页面标题、主体文字大小这些。组件内部独立的、想要跟着组件自身font-size缩放的东西用em。

你那个按钮的场景,如果想让按钮字体固定不变,直接用px或者rem都行:

.btn {
font-size: 19.2px; /* 固定值,最省心 */
/* 或者 */
font-size: 1.2rem; /* 相对于html根字体,不受父元素影响 */
}


如果你希望按钮字体能跟着父容器变化(比如不同业务线想统一缩放),那就明确在父容器上设置font-size,用em:

/* 父容器设置 */
.container {
font-size: 16px;
}

/* 子元素用em */
.btn {
font-size: 1.2em; /* 相对于container的16px */
}


Vue组件里我的习惯做法是:

组件内部样式统一用px或者rem,em尽量别用,除非你非常确定这个组件的上下文。如果组件需要接受外部的字体大小影响,用em配合props明确传值,而不是依赖隐式的父元素查找。

简单说就是:rem用于需要全局一致的场景,em用于组件内部需要相对父级缩放的场景,其他情况直接用px省心。
点赞
2026-03-12 19:01
设计师宝玲
这个问题其实不怪em,是你被Vue的scoped样式坑了一道。

先说你的代码为什么出问题。你给的例子其实逻辑是对的,container设了16px,btn的1.2em应该是19.2px。但如果你实际感觉"变大好多",很可能是父级还有其他的font-size继承,或者你的项目里html根字体设的不是常规的16px(比如很多移动端用62.5%让1rem=10px)。

em和rem的核心区别你理解对了:em相对于最近有font-size的父元素,rem始终相对于html根节点。

在Vue组件里我的建议是:能用rem就用rem,为什么?

1. em在组件嵌套时会变得不可控。你这个按钮可能放在不同的父组件里,父组件的font-size不一样,btn的大小就跟着变,根本不知道当前是多大。

2. rem全局统一,html设一次,全项目都用这个基准,好维护。

具体用法很简单:

html {
font-size: 16px; / 或者用62.5%让1rem=10px /
}

然后组件里:


如果你非要用em也行,但记住两点:要么确保父级font-size是固定值,要么在当前组件里明确重置font-size。可以在组件根元素上显式写 font-size: 16px; 覆盖掉继承。

移动端响应式的话,还可以结合css变量和媒体查询来动态调整html的font-size,一套代码适配各种屏幕宽度。
点赞
2026-03-10 22:01