CSS – rem, em, px
参考:
掘金 – 如何更愉快地使用em —— 别说你懂CSS相对单位
绝对值 vs 相对值
px, cm, mm 这些是绝对值.
rem, em 是相对值.
绝对值就是最终的尺寸. 相对值的意思是它不是最终值, 它依赖另一个变量去决定最终值.
比如
font-size: 16px 那么最终值就是 16px.
font-size: 1rem. 表示依据用户游览器配置决定最终值, 比如, 游览器默认是 1rem = 16px, 所以最终是 16px. (注: 如果用户去调游览器, 那么最终可能变成 1rem = 24px, 36px, 48px... 等等)
em
<p><span>Hello</span></p>
p { font-size: 50px; margin-top: 2em; }
最终 margin-top = 100px. em 就是依据当前 element 的 font-size. 所以 2em = 2 x 50px = 100px.
效果
em use in font-size
如果把 em apply 到 font-size
body { font-size: 50px; } p { font-size: 2em; /* 2 x 50px = 100px */ margin-top: 2em; /* 2 x 100px = 200px */ }
游览器会先查看 p 原始的 font-size. 在上面这个例子中, p 继承 body 的 font-size, 所以 p 的原始 font-size 是 50px.
然后游览器会以 1em = 50px 的基础去计算最终 p 的 font-size. 也就是 2em = 2 x 50px = 100px. 所以最终 p 的 font-size 是 100px.
margin-top 的 2 em 又基于 p 的最终 font-size, 所以是 2 x 100px = 200px. 最终 margin-top 为 200px.
rem
rem 的 r 是 root 的意思, 所以它对标的是 root font-size.
root font-size 指的是 :root 或者 html (不是 body 哦) 的 font-size, 如果没有设定的话, 那它表示游览器的 font-size.
html { font-size: 50px; } p { font-size: 2rem; /* 2 x 50px = 100px*/ }
没有设定 html 的话
p { font-size: 2rem; /* 2 x 16px = 32px*/ }
游览器默认 font-size 是 16px
复杂的例子
它的依赖关系是 p > html > browser
html { font-size: 1.5rem; /* 1.5 x 16px = 24px*/ } p { font-size: 2rem; /* 2 x 24px = 48px*/ }
配合 em 的复杂例子
html { font-size: 1.5rem; /* 1.5 x 16px = 24px*/ } p { font-size: 2rem; /* 2 x 24px = 48px*/ margin-top: 2em; /* 2 x 48px = 96px */ }
font-size should use 绝对值 or 相对值 ?
相对值, 对于用户来说是比较好的, 比如老人家眼力不好, 看字比较吃力, 那么他可以调大字体. 这样就比较容易阅读.
<body> <p class="p1">Hello World</p> <p class="p2">Hello World</p> </body>
CSS Style
.p1 { font-size: 16px; } .p2 { font-size: 1rem; }
效果
setting chrome font size
效果
绝对值的好处是对设计师 (比如 apple.com) 而言的
统一设计 (不容游览器 default font-size 不一定相同)
代码直观 (一般设计师无法直接 convert 4rem to 64px)
我个人觉得用相对值会好一些. 把权力交给用户.
How to apply font-size rem?
直接写 rem
p { font-size: 4rem; }
假设游览器 16px, 那么最终值就是 64px
这种做法最大的缺点就是不直观. 没有办法很快的感知到 4 rem 多大. 因为大家比较习惯看 px.
于是就出现了第 2 种做法
override root
:root { font-size: 62.5%; } p { font-size: 4rem; // 40px // font-size: 2.4rem; // 24px }
root font-size 是可以设定的, :root {} 或者 html {}. 如果没有设定会拿游览器 font-size.
那为什么是 percentage? 为什么是 62.5%
percetage 的意思是拿 parent font-size 的百分比, 假设游览器是 16px
:root 62.5% 就是 16 x 62.5 / 100 = 10px
于是 1 rem = 10px. 24px = 2.4rem
这样从 rem convert to px 就直观多了. 同时它依然随着用户的设置增大或变小, 完美解决问题.
media query adjust
另外稍微动点手脚
@media (min-width: 1280px) { :root { font-size: 70.3125%; } }
还可以让电脑版把 base-font-size 16px 升去 18px.
Scss function + CSS variables
override root 最怕遇到 third party 库. 比如引入 Material Design MDC
它的 CSS font-size 是 1rem, 你把 root 改成 1rem = 1px, 直接 gg.com
所以还有一种写法就是利用 Scss function + CSS variable
:root { --rem-ratio: 1; } @media (min-width: 640px) { :root { --rem-ratio: 1.125; } } @function px2rem($value) { // 游览器默认 1 rem = 16px, 这里 hardcode 16 就好了 @return calc($value * 1rem / 16 * var(--rem-ratio)); } h1 { // mobile 4rem = 64px // laptop 4.4rem = 72px font-size: px2rem(64); }
这个也是我目前用着的方案.
padding, margin, media query, width should use rem or em?
参考:
Medium – Don’t use rem/em for paddings, margins and more (don't use rem/em for margin)
Youtube – Learn HTML & CSS in 2022 | Crash Course (rem for font-size, em for padding margin)
Comprehensive Guide: When to Use Em vs. Rem
首先搞清楚几个关键点.
第一, rem, em 是相对值, 对应的是 font-size 字体尺寸
第二, 当老人家放大字体的时候, 他是看不清楚字而已, 而不是全部内容. 如果是全部内容都小, 他会用 zoom in 而不是 setting font-size.
如果把所以的 px 都换成 rem 那肯定是不合理的, 因为那和 zoom in 就没有区别了呀.
所以关键就是, 如果一个尺寸, 当网页字体变大时, 它也需要变大, 那么就应该用 rem 或 em.
width, media query 都不应该用 rem. font-size 肯定是 rem.
所以最后只剩下 padding 和 margin 需要纠结了.
绝大部分的时候, 当字体变大时, padding 和 margin 也需要变大.
字体小的时候, 2 个 button padding 一致
字体大以后, 第一个 button 的 padding 还是一样, 第二个随着字体一起变大了
通常第 2 个会比较符合预期 (当然也不是说 100%).
这也是为什么会有人建议用 em 来做 padding margin.
但是, BUT!
用 em 是有代价的, 这也是为什么也有许多人建议用 rem (比如 Tailwind CSS)
em 的代价是间距不直观, 不容易控制, 比如有一个 h1 和 p
想做一个间距在中间.
用 gap, 那么 1 em = 16px
用 h1 margin-bottom 那么 1 em = 32px (有时候可能是 5x-6x px)
用 p margin-top 那么 1 em = 16px
不同的 font-size 间距都是 1em, 但是出来的效果都不一样. 这样做间距的时候就很烦. 毕竟我们更习惯用 px 然后转换成 rem 就好了.
所以我的看法是, 如果你能用 em, 用的流畅, 那就用 em 咯. 如果你觉得很反直觉. 那么就用 rem 就好了.
要记得, 只有换局部 font-size 时, 这个 em 才有优势 (这种需求并没有很多), 换整体 font-size, 用 rem 就足够满足效果了.