V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Can I use?
http://caniuse.com/
Less
http://lesscss.org
Cool Libraries
Bootstrap from Twitter
Jetstrap
iFat3
V2EX  ›  CSS

[基础] EM 还是 REM?这是一个问题!

  •  
  •   iFat3 · 2018-04-20 14:52:00 +08:00 · 2923 次点击
    这是一个创建于 2445 天前的主题,其中的信息可能已经有所发展或是发生改变。

    简言

    应用象EMREM这种相对长度单位进行页面排版是 WEB 开发中的最佳实践。在页面排版中较好应用EMREM,根据设备尺寸缩放显示元素的大小。这就使得组件在不同设备上都达到最佳的显示效果成为可能。

    但问题是究竟该用 EM 还是 REM 呢?关于这个问题一直存在比较大的争议。本文将会给大家介绍究竟什么是 EMREM 和如何进行两者的选择,以及结合两者优势构建模块化的 WEB 组件。

    注:本文内容简单,只面向初级开发人员,约 2500 字,阅读时间 5 分钟。

    1 什么是 EM ?

    em 是相对长度单位。它相对于当前元素字体尺寸,即font-size。举例来说,如果当前元素的字体是 20px,那么当前元素中的 1em 就等于 20px。

    h1 { font-size: 20px } /* 1em = 20px */
    p { font-size: 16px } /* 1em = 16px */
    

    实际开发中,用相对长度单位(如 em)表示字体大小是 WEB 开发中的最佳实践。

    考虑下面的代码:

    h1 { font-size: 2em } 
    

    这里的 h1 元素字体大小究竟是多少呢?

    这时,我们需要根据<h1>父元素字体的大小,来计算<h1>字体的尺寸大小。如果父元素是<html>,而且<html>的字体大小是 16px。就可以计算出<h1>的字体大小是 32px,即 2*16px。

    用代码表示如下:

    html { font-size: 16px }
    h1 { font-size: 2em } /* 16px * 2 = 32px */
    

    设置<html>字体的大小一般来说都不是一个好主意,因为这样重写了用户浏览器的默认设置。相反,可以使用百分比值或者根本不声明<html>字体大小。

    html { font-size: 100% } /* 缺省 16px */
    

    对于大多数用户或浏览器,字体缺省大小是 16px (未做浏览器缺省字体尺寸设置)。

    em 还能用来指定除字体大小外的其它属性,象marginpadding等属性都可以用em来表示。

    考虑下面的代码, 对于<h1><p>元素,margin-bottom值应该是多少? (假设<html>的字号被设置为 100 %)。

    h1 {
      font-size: 2em; /* 1em = 16px */
      margin-bottom: 1em; /* 1em = 32px */
    }
    p {
      font-size: 1em; /* 1em = 16px */
      margin-bottom: 1em; /* 1em = 16px */
    }
    

    上述<h1><p>的 margin-bottom 都是 1em,但是外边距结果值却不相同。上述现象的出现,是因为em是相对于当前元素字体的大小。由于<h1>中的字体大小现在设置为 2em, 因此<h1>中其它属性的 1em 值就是 1em = 32px。这里比较容易引起误解的地方。

    2 什么是 REM ?

    rem表示 root em,它是相对于根元素的长度单位。这里根元素就是<html>中定义的字体大小。这意味着任何地方的 1rem 总是等于<html>中定义的字体大小。

    利用上述相同的代码,我们用 rem 来代替 em,查看margin-bottom的计算值究竟是多少?

    h1 {
      font-size: 2rem;
      margin-bottom: 1rem; /* 1rem = 16px */
    }
    p {
      font-size: 1rem;
      margin-bottom: 1rem; /* 1rem = 16px */
    }
    

    如上述代码所示,1rem 总是等于 16px (除非变更了<html>字体的大小)。rem的大小相较于em来说意义更直接明确,也很容易理解。

    3 REM 还是 EM?

    在项目开发中究竟是选用 rem 还是 em 一直以来争议不断。一些开发人员不使用rem,因为rem使组件不那么模块化。而另一些开发人员喜欢rem的简单性,使用rem处理所有元素。

    其实 emrem都有各自的优势和劣势,在实际项目开发中,应该结合使用两者,利用各自的优势,从而实现较好代码质量和显示效果。

    那么在具体的应用中如何在两者中做选择呢?有两条简单的指导原则:

    • 如果属性尺寸要根据元素字体进行缩放,则使用em
    • 其它情况下都使用rem

    上述规则太简单了。 为了更好的理解上述规则,我们就以一个简单的 header 组件为例,说明单独使用两者来实现组件遇到的问题,并体会结合使用两者所带来的优势。

    3.1 只使用 REM

    这里我们只使用rem来编写一个 header 组件,代码及运行结果如下:

    .header {
      font-size: 1rem;
      padding: 0.5rem 0.75rem;
      background: #7F7CFF;
    }
    

    用 rem 实现 header 测试图 1

    接下来,网站需要一个尺寸更大的 header 组件。

    变更 CSS 代码如下:

    .header {
      font-size: 1rem;
      padding: 0.5rem 0.75rem;
      background: #7F7CFF;
    }
    .header-large {
      font-size: 2rem;
    }
    

    运行结果如下:

    用 rem 实现 header 测试图 2

    从上述运行结果可以看出,文字的内边距(padding)过小,显示效果不协调。如果我们坚持只使用rem,只能变更 css 代码如下:

    .header {
      font-size: 1rem;
      padding: 0.5rem 0.75rem;
      background: #7F7CFF;
    }
    .header-large {
      font-size: 2rem;
      padding: 1rem 1.5rem;
    }
    

    变更后运行结果如下:

    用 rem 实现 header 测试图 3

    上述代码及运行结果,虽然达到了预期的显示效果,但却违背了代码复用的原则。如果网站有多种尺寸的.header 样式,就要多次重复的定义内边距。重复的代码增加了项目复杂度,降低了可维护性。

    这时可以利用em可以变更上述代码如下:

    .header {
      font-size: 1rem;
      padding: 0.5em 0.75em;
      background: #7F7CFF;
    }
    .header-large {
      font-size: 2rem;
    }
    

    运行结果请查看演示程序:

    演示代码

    如上述演示程序所示,当元素属性值的大小需要根据元素字体尺寸缩放时,就应该应用 em 来定义属性尺寸。这就是前述规则中的第一条规则。

    3.2 只使用 EM

    如果只使用em来定义上述组件,结果会怎样呢?

    我们变更上述代码如下(em替换rem):

    .header {
      font-size: 1em;
      padding: 0.5em 0.75em;
      background: #7F7CFF;
    }
    .header-large {
      font-size: 2em;
    }
    

    为更接近实际,我们引入了<p>元素,并变更html代码如下:

    <div class="header header-large">名人名言</div>
    <p>简单是稳定的前提</p>
    <div class="header">名人名言</div>
    <p>简单是稳定的前提</p>
    

    增加 p 元素 css 代码如下:

    p {
        padding: 0.5em 0.75em;
    }
    

    运行结果如下:

    用 em 实现 header 测试图 1

    从上述运行经果中,不难看出.header-large部分的标题并没有和文本左对齐。而如果只使用em实现左对齐,则需要变更 CSS 代码如下:

    .header {
      font-size: 1em;
      padding: 0.5em 0.75em;
      background: #7F7CFF;
    }
    .header-large {
      font-size: 2em;
      padding-left: 0.375em;
      padding-right: 0.375em;
    }
    

    变更后运行结果如下:

    用 em 实现 header 测试图 2

    上述代码及运行结果,虽然达到了预期的显示效果,但却违背了代码复用的原则。如果网站有多种尺寸的.header 样式,就要多次重复的定义左右边距。重复的代码增加了项目复杂度,降低了可维护性。

    解决上述问题的办法是结合使用emrem,即使用em定义上下边距,使用rem定义左右边距。变更后代码如下:

    .header {
      padding: 0.5em 0.75rem;
      font-size: 1em;
      background: #7F7CFF;
    }
    
    .header-large {
      font-size: 2em;
    }
    

    运行结果请查看演示程序:

    演示代码

    3.3 EM 还是 REM 总结

    究竟是该使用em还是rem呢?答案应该是结合使用remrem。当属性值的大小需要根据当前元素字体尺寸缩放时,就选用em,其它的情况都使用更简单的rem

    4 em 及 rem 值的设定

    emrem 属性值都要经过计算转化成绝过长度单位。常用的字体尺寸用相对长度单位表示会很困难。看下面常用字体值的rem表示(基本字体尺寸是 16px ):

    • 10px = 0.625rem
    • 12px = 0.75rem
    • 14px = 0.875rem
    • 16px = 1rem (base)
    • 18px = 1.125rem
    • 20px = 1.25rem
    • 24px = 1.5rem
    • 30px = 1.875rem
    • 32px = 2rem

    如上述列表所示,上述尺寸值的表示及计算都不分的不便。为了解决上述问题要用到一个小技巧,即著名的 "62.5%"技术。具体请查看下述代码:

    body { font-size:62.5%; }  /* =10px */
    h1   { font-size: 2.4em; } /* =24px */
    p    { font-size: 1.4em; } /* =14px */
    

    通过 62.5%的设定,就可以很容易用em来定义具体属性的尺寸了( 10 倍的关系)。

    rem,则需要采用如下的方式:

    html { font-size: 62.5%; }  /* =10px */
    body { font-size: 1.4rem; } /* =14px */
    h1   { font-size: 2.4rem; } /* =24px */
    

    5 响应式例子

    一个简单的响应式的例子,调整浏览器宽度查看演示效果。

    演示代码

    6 参考资料

    1. W3C:CSS Values and Units Module Level 3
    2. zellwk:REM vs EM – The Great Debate
    3. sitepoint:Understanding and Using rem Units in CSS
    4. tutsplus:Comprehensive Guide: When to Use Em vs. Rem
    5. css-tricks:Confused About REM and EM?

    7 说明

    文中所述文字及代码部分汇编于网络。因时间不足,能力有限等原因,存在文字阐述不准及代码测试不足等诸多问题。因此只限于学习范围,不适用于实际应用。另emrem在较老的浏览器中存在兼容性问题。

    目前尚无回复
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   933 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 19:40 · PVG 03:40 · LAX 11:40 · JFK 14:40
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.