찾다
웹 프론트엔드HTML 튜토리얼REM vs EM_html/css_WEB-ITnose

网页字体排版的最佳实践之一就是使用相对单位,如 rem 和 em .

问题是,你应该使用哪一个呢?一直以来, rem 支持者和 em 支持者之间都存在着争辩,认为应该使用自己支持的那个。

在这篇文章中,你会找到我如何在 rem 和 em 之间做抉择.你也将了解 rem 和 em 到底是什么以及如何使用它们来构建模块化组件。

什么是EM?

EM 是字体排印的一个单位,等同于当前指定的point-size。-维基百科

此语句在网页上并不能说得过去,因为我们不使用 point-size .如果我们用 point-size 取代 font-size 的话,这句话就完全行得通。

意思就是,如果存在一个选择器的 font-size 属性的值为 20px ,那么 1em=20px

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

em 单位可以被用来声明字体的大小。实际上,最佳做法是使用相对单位,如用 em 指定 font-size 。

考虑如下代码:

h1 { font-size: 2em }

这里 h1 选择器的真正大小是多少呢?

我们要根据

的父元素来计算 font-size 。它的父元素是 ,并且它的 font-size 被设置为 16px 。

通过这种方式,我们可以计算出 h1 的值为 32px ,或者说 2 * 16px .

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

虽然也可以实现,但是这并不被认为是一个好主意,通过在 中设置 font-size 的像素值将影响用户浏览器所设置的值。

取而代之,你可以使用 percentage 值,或者完全摒弃 font-size 。

注意:如果你完全摒弃 font-size ,它的值将被默认为 100% .

html { font-size: 100% } /*这里的意思是默认值为16px*/

对于大多数的用户(和浏览器), font-size 的值为 100% ,就会默认为 16px ,除非用户通过浏览器设置来改变 font-size 的默认值。但是很少有人这么做。

好了,让我们回到 em 。

em 也可以用来指定除了 font-size 的其它属性值。 margin 和 padding 属性也经常用 em 设置大小。

这里是很多人开始对 em 的值产生困惑的地方。

考虑下面的代码。

元素的 margin-bottom 的值应该是多少?(假设 的 font-size 被设置为 100% ).

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

你是不是很吃惊两种状况下的 margin-bottom 的 1em 值不同?

这种现象的发生在于 1em 等同于它当前的 font-size 。因为

中的 font-size 被设置为了 2em 。其他用在

内的 em 来计算的属性,就为 1em = 32px 。

在不同的代码中, 1em 就会有不同的取值,这就是经常迷惑人们的地方。如果你也是刚刚接触 em ,你也会产生迷惑。

不管怎么说,这就是 em .接下来,让我们认识 rem 。

什么是REM?

rem 指根 em 。 它的产生是为了帮助人们解决 em 所带来的计算问题。

它是字体排版的一个单位,等同于根 font-size 。这意味着 1rem 等同于 中的 font-size 。

考虑相同的用 rem 表示的代码。现在 margin-bottom 计算出来的值为多少呢?

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

正如您看到的,无论您在哪里设置它, 1rem 的取值均为 16px 。

这是十分可靠的,很容易去理解。

这就是 rem 。一旦你知道了什么是 em ,就很容易去理解,你是不是也同意这个观点?

现在让我们步入这篇文章的正题, rem 还是 em ?

REMs or EMs?

这是极具争议的问题。

一些开发人员完全避免使用 rem ,声称使用 rem 会使他们的组件缺少模块化。另外一些人则什么都使用 rem ,因为喜欢 rem 所带来的便捷。

奇怪的是,在我的职业生涯中,我掉进了在不同的地方是使用 rem 或者 em 的陷阱中。我喜欢 em 帮助我完成模块化组件,但是讨厌它所带来的代码复杂性。我喜欢 rem 计算的便捷,但是讨厌他是我模块化组件的阻碍。

事实证明。 rem 和 em 均有各自的优缺点。应给根据实际情况来判断其使用方式。

这里我有两个简单的规则:

  • 如果这个属性根据它的 font-size 进行测量,则使用 em
  • 其他的一切事物均使用 rem .

有点太简单了么?让我们考虑用 rem 还是 em ,来书写一个简单的组件(头部元素),此过程中你就会发现这两个规则发挥的良好作用。

仅使用 rem 来制作标题元素

你有一个看起来如下图所示的标题元素(

):

如果你用 rem 设置一切属性的大小,标题元素的样式应该和上图相似:

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

目前为止,一切都好。

既然在相同的网页上会有不同大小的元素,接下来让我们创建一个稍微大的头部元素。这里,我们尽可能继承样式。

更大元素的标记可能如下所示:

<a href="#" class="header header--large">header!</a>

css样式如下:

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

不幸的是,这个代码并不能实现效果。你会发现在 .header--larger 下,文本和边缘的空间太小。

如果你坚持使用 rem ,唯一的办法就是使用 padding 重新声明大标题:

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

有没有注意到这里的模式? .header--larger 的 font-size 是 header 的两倍大。因此, .header--large 的 padding 是 .header 的两倍大小。

如果我们有更多大小的标题,或者改变标题大小时,又会发生什么呢?你已经可以看到如果使用 rem 对整个网站进行编码所带来的重复性以及复杂性。

我们可以同时使用 rem 和 em 简化代码,这样就不需要对 .header-larger 的 padding 进行声明。

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

正如你所看到的, 当有属性需要用它的字体大小( font-size )进行大小声明时,这时 em 就相当有用。 这就是第一条原则产生的地方。

接下来让我们看看,如何只使用 em 来创建相同的标题。

只使用 EMs 制作标题元素

只使用 em 来制作标头元素和只使用 rem 制作的代码差不多,只需要将 rem 该更为 em .

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

.header 和 .header--larger 的效果看起来和 rem 实现效果一样。

不是吗?

不是的!

你的网页只包含一个标题元素是极不可能的。我们必须考虑标题与页面其他元素的交互。

在标题之前或之后看见其他元素是十分正常的,如下图所示:

对于这个元素集的标记如下:

<div class="header header--large">A Header Element</div><p>A paragraph of text</p><p>A paragraph of text</p><div class="header">A Header Element</div><p>A paragraph of text</p>

对于样式,我们需要对 p 标签的左边和右边添加一点外边距:

p {  margin-left: 0.75em;  margin-right: 0.75em;}

不不不! :(

.header--larger 左边和右边的 padding 太大了!

如果你坚持只使用 em 来解决这个问题,唯一的方法就是重新声明大标头的 padding-left 和 pading-right .

.header {  font-size: 1em;  padding: 0.5em 0.75em;  /* Other styles */}.header--large {  font-size: 2em;  padding-left: 0.375em;  padding-right: 0.375em;  margin: 0.75em 0; }

注意到这里的模式了么? .header--larger 的 font-size 是 .header 的 font-size 的两倍大小,然而 .header--larger 的 padding-left 和 padding-right 是 .header 的一半。

在上述的案例中,如果我们可以同时使用 em 和 rem 就可以简化代码。具体来说就是, em 负责 padding 的左边和右边, rem 负责 padding 的顶部和底部。

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

正如你所看到的,当一个元素用 font-size 声明大小时, em 单位是十分有用的。但是,当你需要根据根 font-size 来设置属性大小时,你就会陷入麻烦之中。

在一个组件之中看 rem 和 em 如何配合工作,不是更加清楚么?

现在,让我们提高一个档次,看标题和段落之间如何在网格中进行交互。

网格组件

在这之前,让我们先把标题和段落组成一个组件:

<div class="component">  <div class="component__header">A header element</div>  <p>Some paragraph text</p></div>

组件的基本样式为:

.component {  background: white;  border: 2px solid #7F7CFF;}.component__header {  font-size: 2em;  padding: 0.5em 1.5rem;  background: #7F7CFF;  margin: 0;}.component p {  padding-left: 1.5rem;  padding-right: 1.5rem;  margin: 1.5rem 0;}

目前为止,一切都好。这都是我们在前面的章节所涵盖的。

我们可以在不同的网页中找到此组件,可能的领域包括:

  • 主要内容区域
  • 侧边栏
  • 在一个 1/3 的网格布局中

当组件被放置在一个较小的位置时,如侧边栏。这时,标题元素就会使用一个较小的 font-size 来呈现。

通过修改组件的类,我们可以创建变量。标记将如下所示:

<div class="component component--small">  <!-- Contents of the component. --></div>

变量的样式如下:

.component--small .component__header {  font-size: 1em;}

现在,关于组件的样式,两条规则同样适用:

  • 如果这个属性根据它的 font-size 进行测量,则使用 em
  • 其他的一切事物均使用 rem

通过标题元素,我们了解到,是否使用 em 进行大小声明,只需判断该属性是否与页面其他元素进行交互。这里有两种不同的方式来思考如何构建此组件:

  • 所有内联元素缩放都根据组件的 font-size 决定。
  • 部分内联元素缩放根据组件的 font-size 决定。

让我们用两种方式构建组件,你就会明白我的意思。

案例1: 所有内联元素缩放都根据组件的 font-size 决定

我们通过一个例子来看这样子的组件是什么样子:

注意当组件的大小改变时,同一时间内 font-size 、 margin 和 padding 的变化。

当组件大小变化时,如果您想要这样的效果,那么就需要使用 em 进行大小声明:

.component {  background: white;  border: 2px solid #7F7CFF;}.component__header {  font-size: 2em;  padding: 0.5em 0.75em; /* Changed padding into em */  background: #7F7CFF;  margin: 0;}.component p {  padding-left: 1.5em; /* Changed padding into em */  padding-right: 1.5em; /* Changed padding into em */  margin: 1.5em 0; /* Changed margin into em */}// Small variant .component--small .component__header {  font-size: 1em;  padding-left: 1.5em; /* Added em-sized padding */  padding-right: 1.5em; /* Added em-sized padding */}

然后,要激活变化大小,你不得不更改组件的 font-size 属性。

.component {  // Other styles  @media (min-width: 800px) {    font-size: 1.5em;  }}

目前为止,一切都好。

现在,让我们开始复杂部分。

想象一下你是否有一个这样子的网格。每个网格项之间的垂直和水平空间在不同设备上需要保持一致(良好的美学需要).

网格标记为:

<div class="grid">  <div class="grid-item">     <div class="component"> <!-- component --> </div>   </div>  <div class="grid-item">    <div class="component component--small"> <!-- A --> </div>    <div class="component component--small"> <!-- B --> </div>  </div></div>

在根 font-size 大小为 16px 的情况下,我已经将每个网格项之间的间距设置为 2em 。换句话说,间距计算的宽度为 32px 。

在这个网格之中的挑战就是,小组件A和小组件B之间要保持 32px 的外边距。开始的时候我们可以将组件B的 margin-top 设置为 2em 。

.component {  /* Other styles */  @media (min-width: 800px) {    font-size: 1.25em;  }}.component + .component {  margin-top: 2em;}

不幸的是,这效果并不是很好。小组件A和小组件B之间的 margin 的大小在视觉上远远大于视窗宽度 800px 时的列间距。

这种情况的发生是因为当视窗大于 800px 时,组件的 font-size 大小为 1.5em ( 24px )。因为 font-size 为 24px ,所以 2em 就是 48px ,这不同于我们所期待的 32px .

幸运的是,当我们知道是根据 font-size 来设置列间距大小时,我们就可以用 rem 轻易地解决这个问题。

.component + .component {  margin-top: 2rem;}

这里有一个Codepen,你可以尝试一下。

注意:你需要用Flexbox来创建此网格。这里我将不再过多的解释,因为不仅仅是代码问题。如果你想了解更多关于Flebox的知识,你可以参考这里的文章。

顺便说一下,我没有赶上这一技术。Chris Coyier(他是一个天才)在一年之前就写了 它 。

不管怎样,我们就到目前为止好吗?如果好的话,让我们转向案例2。如果不好的话,有时间就留下评论,我会想办法作进一步解释。

案例2:部分内联元素缩放根据组件的 font-size 决定

案例1很容易理解。缺点是 很难保持模块化缩放,主要是垂直方向间距(vertical rhythms)并且在同一组件内保持大小一致 (特别是建设响应式网站)。

有时候你只需要调整组件的一部分,而不是一次性调整所有部分。例如,您可能仅仅想要更改一个较大视区标题的 font-size 。

在这种情况下,让我们先看看如何书写基本样式:

.component {  background: white;  border: 2px solid #7F7CFF;}.component__header {  font-size: 2em;  padding: 0.5em 1.5rem;  background: #7F7CFF;  margin: 0;}.component p {  padding-left: 1.5rem;  padding-right: 1.5rem;  margin: 1.5rem 0;}.component--small .component__header {  font-size: 1em;}

既然我们只是更改标题的 font-size 为 1200px ,我们可以使用 rem 控制一切属性的大小(不包括标题的 padding-top 和 padding-bottom 属性)

.component {  background: white;  border: 2px solid #7F7CFF;}.component__header {  font-size: 2rem; /* Sized in rem instead */  padding: 0.5em 1.5rem; /* Sized in rem instead */  background: #7F7CFF;}.component p {  padding-left: 1.5rem; /* Sized in rem instead */  padding-right: 1.5rem; /* Sized in rem instead */  margin: 1.5rem 0; /* Sized in rem instead */}.component--small .component__header {  font-size: 1rem; /* Sized in rem instead */}

然后你就可以通过在不同视区下增加一个媒体特性,来更改标题的 font-size .

.component__header {  font-size: 2rem;  @media (min-width: 1200px) {    font-size: 3rem  }}.component--small .component__header {  font-size: 1rem;  @media (min-width: 1200px) {    font-size: 1.5rem  }}

注意,当我们改变浏览器大小时,标题 font-size 是如何改变的。这就是我们创建的案例2:)

还有一件事。

因为最好只使用少量的字体大小,我经常从组件上发现抽象的 font-size 属性。这种方式可以轻松的实现在所有组件上保持字体大小。

h2 {   font-size: 2rem;  @media (min-width: 1200px) {    font-size: 3rem  } }h3 {   font-size: 1rem;   @media (min-width: 1200px) {    font-size: 1.5rem  }}.component__header { @extend h2; }.component--small .component__header { @extend h3; }

这就是案例2!这里有一个Codepen供你去尝试:

这里你可能会问一个问题,“你应该使用哪种方法呢?”所以我还是先回答吧。

我会回答,这取决于您的设计。

就我个人而言,自从喜欢上自由文字排版模式,我使用案例2的时候相对多一点。

总结

所以,你应该使用 rem 或者 em 吗?我想这并不是一个很好的问题。 rem 和 em 都各有优缺点,应该综合使用它们以帮助您更简单的建立模块化组件。

扩展阅读

  • Rem VS Px
  • CSS中强大的EM
  • CSS3的REM设置字体大小
  • Sass基础——Rem与Px的转换
  • Sass函数功能——rem转px
  • 何时使用 Em 与 Rem

本文根据 @Zell 的《 REM vs EM – The Great Debate 》所译,整个译文带有我们自己的理解与思想,如果译得不好或有不对之处还请同行朋友指点。如需转载此译文,需注明英文出处: http://zellwk.com/blog/rem-vs-em/ 。

静子

在校学生,本科计算机专业。一个积极进取、爱笑的女生,热爱前端,喜欢与人交流分享。想要通过自己的努力做到心中的那个自己。微博:@静-如秋叶

성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
HTML의 역할 : 웹 컨텐츠 구조HTML의 역할 : 웹 컨텐츠 구조Apr 11, 2025 am 12:12 AM

HTML의 역할은 태그 및 속성을 통해 웹 페이지의 구조와 내용을 정의하는 것입니다. 1. HTML은 읽기 쉽고 이해하기 쉽게하는 태그를 통해 컨텐츠를 구성합니다. 2. 접근성 및 SEO와 같은 시맨틱 태그 등을 사용하십시오. 3. HTML 코드를 최적화하면 웹 페이지로드 속도 및 사용자 경험이 향상 될 수 있습니다.

HTML 및 코드 : 용어를 자세히 살펴 봅니다HTML 및 코드 : 용어를 자세히 살펴 봅니다Apr 10, 2025 am 09:28 AM

"Code"는 "Code"BroadlyIncludeLugageslikeJavaScriptandPyThonforFunctureS (htMlisAspecificTypeofCodeFocudecturecturingWebContent)

HTML, CSS 및 JavaScript : 웹 개발자를위한 필수 도구HTML, CSS 및 JavaScript : 웹 개발자를위한 필수 도구Apr 09, 2025 am 12:12 AM

HTML, CSS 및 JavaScript는 웹 개발의 세 가지 기둥입니다. 1. HTML은 웹 페이지 구조를 정의하고 등과 같은 태그를 사용합니다. 2. CSS는 색상, 글꼴 크기 등과 같은 선택기 및 속성을 사용하여 웹 페이지 스타일을 제어합니다.

HTML, CSS 및 JavaScript의 역할 : 핵심 책임HTML, CSS 및 JavaScript의 역할 : 핵심 책임Apr 08, 2025 pm 07:05 PM

HTML은 웹 구조를 정의하고 CSS는 스타일과 레이아웃을 담당하며 JavaScript는 동적 상호 작용을 제공합니다. 세 사람은 웹 개발에서 의무를 수행하고 화려한 웹 사이트를 공동으로 구축합니다.

HTML은 초보자를 위해 쉽게 배우나요?HTML은 초보자를 위해 쉽게 배우나요?Apr 07, 2025 am 12:11 AM

HTML은 간단하고 배우기 쉽고 결과를 빠르게 볼 수 있기 때문에 초보자에게 적합합니다. 1) HTML의 학습 곡선은 매끄럽고 시작하기 쉽습니다. 2) 기본 태그를 마스터하여 웹 페이지를 만들기 시작하십시오. 3) 유연성이 높고 CSS 및 JavaScript와 함께 사용할 수 있습니다. 4) 풍부한 학습 리소스와 현대 도구는 학습 과정을 지원합니다.

HTML의 시작 태그의 예는 무엇입니까?HTML의 시작 태그의 예는 무엇입니까?Apr 06, 2025 am 12:04 AM

anexampleStartingtaginhtmlis, whithbeginsaparagraph.startingtagsareessentialinhtmlastheyinitiate rements, definetheirtypes, andarecrucialforstructurituringwebpages 및 smanstlingthedom.

메뉴에서 점선 분할 효과의 중심 정렬을 달성하기 위해 CSS의 Flexbox 레이아웃을 사용하는 방법은 무엇입니까?메뉴에서 점선 분할 효과의 중심 정렬을 달성하기 위해 CSS의 Flexbox 레이아웃을 사용하는 방법은 무엇입니까?Apr 05, 2025 pm 01:24 PM

메뉴에서 점선 분할 효과를 설계하는 방법은 무엇입니까? 메뉴를 설계 할 때는 일반적으로 접시 이름과 가격 사이에 왼쪽과 오른쪽을 정렬하는 것이 어렵지 않지만 점선 또는 중간의 점은 어떻습니까?

온라인 코드 편집기는 코드 입력을 구현하는 데 사용하는 HTML 요소는 무엇입니까?온라인 코드 편집기는 코드 입력을 구현하는 데 사용하는 HTML 요소는 무엇입니까?Apr 05, 2025 pm 01:21 PM

웹 코드 편집기의 HTML 요소 분석 많은 온라인 코드 편집기를 사용하면 사용자가 HTML, CSS 및 JavaScript 코드를 입력 할 수 있습니다. 최근에 누군가가 제안했습니다 ...

See all articles

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

AI Hentai Generator

AI Hentai Generator

AI Hentai를 무료로 생성하십시오.

인기 기사

R.E.P.O. 에너지 결정과 그들이하는 일 (노란색 크리스탈)
3 몇 주 전By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. 최고의 그래픽 설정
3 몇 주 전By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. 아무도들을 수없는 경우 오디오를 수정하는 방법
3 몇 주 전By尊渡假赌尊渡假赌尊渡假赌
WWE 2K25 : Myrise에서 모든 것을 잠금 해제하는 방법
3 몇 주 전By尊渡假赌尊渡假赌尊渡假赌

뜨거운 도구

SecList

SecList

SecLists는 최고의 보안 테스터의 동반자입니다. 보안 평가 시 자주 사용되는 다양한 유형의 목록을 한 곳에 모아 놓은 것입니다. SecLists는 보안 테스터에게 필요할 수 있는 모든 목록을 편리하게 제공하여 보안 테스트를 더욱 효율적이고 생산적으로 만드는 데 도움이 됩니다. 목록 유형에는 사용자 이름, 비밀번호, URL, 퍼징 페이로드, 민감한 데이터 패턴, 웹 셸 등이 포함됩니다. 테스터는 이 저장소를 새로운 테스트 시스템으로 간단히 가져올 수 있으며 필요한 모든 유형의 목록에 액세스할 수 있습니다.

Dreamweaver Mac版

Dreamweaver Mac版

시각적 웹 개발 도구

MinGW - Windows용 미니멀리스트 GNU

MinGW - Windows용 미니멀리스트 GNU

이 프로젝트는 osdn.net/projects/mingw로 마이그레이션되는 중입니다. 계속해서 그곳에서 우리를 팔로우할 수 있습니다. MinGW: GCC(GNU Compiler Collection)의 기본 Windows 포트로, 기본 Windows 애플리케이션을 구축하기 위한 무료 배포 가능 가져오기 라이브러리 및 헤더 파일로 C99 기능을 지원하는 MSVC 런타임에 대한 확장이 포함되어 있습니다. 모든 MinGW 소프트웨어는 64비트 Windows 플랫폼에서 실행될 수 있습니다.

VSCode Windows 64비트 다운로드

VSCode Windows 64비트 다운로드

Microsoft에서 출시한 강력한 무료 IDE 편집기

에디트플러스 중국어 크랙 버전

에디트플러스 중국어 크랙 버전

작은 크기, 구문 강조, 코드 프롬프트 기능을 지원하지 않음