我正在设计一个新的网站,我希望它能与尽可能多的浏览器和浏览器设置兼容。我试图决定我应该使用什么测量单位的字体和元素的大小,但我无法找到一个结论性的答案。

我的问题是:我应该在CSS中使用px还是rem ?

到目前为止,我知道使用px不兼容那些在浏览器中调整基本字体大小的用户。 我忽略了ems,因为与rem相比,它们在级联时维护起来更麻烦。 有人说rem是分辨率独立的,因此更可取。但也有人说,大多数现代浏览器对所有元素都一视同仁,所以使用px不是问题。

我问这个问题是因为关于CSS中最理想的距离度量有很多不同的意见,我不确定哪个是最好的。


当前回答

我想赞扬josh3736的回答提供了一些优秀的历史背景。虽然这个问题已经很清楚地表达出来了,但自从这个问题被提出以来,CSS的前景在近五年内已经发生了变化。当这个问题被问到时,px是正确答案,但今天它不再成立。


Tl;dr:用rem

单位概述

历史上,px单位通常代表一个设备像素。随着设备的像素密度越来越高,这种方法不再适用于许多设备,比如苹果的Retina Display。

Rem单位代表根em大小。它是匹配root的字体大小。在HTML的情况下,它是< HTML >元素;对于SVG,它是< SVG >元素。每个浏览器的默认字体大小*是16px。

关于使用px

互联网上的大多数CSS示例都使用px值,因为它们是事实上的标准。Pt, in和其他各种单位在理论上都可以使用,但它们不能很好地处理小的值,因为你很快就需要求助于分数,这需要更长时间输入,而且很难推理。

如果你想要一个细边框,px你可以使用1px, pt你需要使用0.75pt来获得一致的结果,这不是很方便。

关于rem的使用

Rem的默认值16px并不是一个很好的使用理由。写入0.0625rem比写入0.75pt更糟糕,那么为什么有人会使用rem呢?

雷姆与其他单位相比有两方面的优势。

尊重用户偏好 你可以随意改变rem的表观px值

尊重用户偏好

多年来,浏览器缩放功能发生了很大变化。从历史上看,许多浏览器只会扩大字体大小,但当网站意识到他们漂亮的像素完美设计在任何时候都被放大或缩小时就会被破坏时,这种情况就会迅速改变。此时,浏览器会缩放整个页面,因此基于字体的缩放就不存在了。

尊重用户的意愿并不是不可能的。仅仅因为浏览器默认设置为16px,并不意味着任何用户不能将首选项更改为24px或32px以纠正低视力或低能见度(例如屏幕眩光)。如果您以rem为单位,那么任何字体大小较高的用户都会看到相应较大的站点。边界会更大,填充会更大,边际会更大,一切都将流动地扩大。

如果您的媒体查询基于rem,您还可以确保您的用户看到的网站适合他们的屏幕。如果用户在640px宽的浏览器上将字体大小设置为32px,那么在320px宽的浏览器上,用户将有效地看到以16px宽的字体显示的站点。在使用rem时,响应式网页设计(RWD)绝对没有损失。

改变表观px值

因为rem是基于:根节点的字体大小,如果你想改变1rem所代表的东西,你所要做的就是改变字体大小:

:根{ 字体大小:100 px; } 身体{ 字体大小:1快速眼动; } <p>请不要真的这样做

无论你做什么,不要将:root元素的font-size设置为px值。

如果将html上的font-size设置为px值,就会破坏用户的首选项,而无法将其返回。

如果你想改变rem的表观值,使用%单位。

这方面的数学计算相当简单。

:root的字体大小是16px,但是我们想把它改成20px。我们要做的就是用16乘以一个值得到20。

建立方程:

16 * X = 20

解出X:

X = 20 / 16
X = 1.25
X = 125%

:根{ 字体大小:125%; } 如果你使用默认的字体大小,我是20px高

用20的倍数来做所有事情并不是很好,但一个常见的建议是让rem的表观大小等于10px。神奇的数字是10/16,也就是0.625,即62.5%。

:根{ 字体大小:62.5%; } 如果你使用默认的字体大小,我是10px高

现在的问题是,页面其余部分的默认字体大小设置得太小了,但有一个简单的解决方法:使用rem设置正文的字体大小:

:根{ 字体大小:62.5%; } 身体{ 字体大小:1.6快速眼动; } 我是默认的字体大小</p>

需要注意的是,调整到位后,rem的表观值为10px,这意味着任何用px表示的值都可以通过碰撞小数位直接转换为rem。

padding: 20px;

变成

padding: 2rem;

你选择的字体大小取决于你,所以如果你想要,没有理由你不能使用:

:root {
  font-size: 6.25%;
}
body {
  font-size: 16rem;
}

让1rem等于1px。

所以你有了它,一个简单的解决方案,尊重用户的愿望,同时也避免过度复杂的CSS。

等等,这里面有什么玄机?

我就怕你会这么问。尽管我很想假装rem是魔法,可以解决所有问题,但还是有一些值得注意的问题。在我看来,这没什么大不了的,但我会把他们叫出来,这样你就不能说我没有警告过你。

媒体查询(使用em)

使用rem会遇到的第一个问题是媒体查询。考虑下面的代码:

:root {
  font-size: 1000px;
}
@media (min-width: 1rem) {
  :root {
    font-size: 1px;
  }
}

这里rem的值取决于是否应用media-query,而media查询取决于rem的值,那么到底发生了什么?

rem在媒体查询中使用font-size的初始值,并且不应该(参见Safari部分)考虑:root元素的font-size可能发生的任何变化。换句话说,它的表观值总是16px。

这有点烦人,因为这意味着您必须进行一些分数计算,但我发现大多数常见的媒体查询已经使用了16的倍数的值。

|   px | rem |
+------+-----+
|  320 |  20 |
|  480 |  30 |
|  768 |  48 |
| 1024 |  64 |
| 1200 |  75 |
| 1600 | 100 |

此外,如果你正在使用CSS预处理器,你可以使用mixin或变量来管理你的媒体查询,这将完全掩盖问题。

Safari

不幸的是,Safari有一个已知的bug,更改:root font-size实际上会更改媒体查询范围的计算rem值。如果在媒体查询中改变了:root元素的font-size,则会导致一些非常奇怪的行为。幸运的是,解决方法很简单:使用em单位进行媒体查询。

上下文切换

如果您在不同的项目之间切换,rem的表观字体大小很可能具有不同的值。在一个项目中,你可能会使用10px的表观大小,而在另一个项目中,表观大小可能是1px。这可能会让人困惑并导致问题。

在这里,我唯一的建议是坚持使用62.5%来将rem转换为10px的表观大小,因为在我的经验中,这是更常见的。

共享CSS库

如果您编写的CSS将用于您无法控制的站点,例如嵌入式小部件,那么实际上没有好方法知道rem的表观大小。如果是这种情况,可以继续使用px。

如果您仍然想使用rem,可以考虑使用一个变量发布样式表的Sass或LESS版本,以覆盖rem表观大小的缩放。


*我不想吓走任何人使用rem,但我还不能正式确认每个浏览器默认使用16px。你看,有很多浏览器,对于一个浏览器来说,稍微偏离15px或18px并不难。然而,在测试中,我还没有看到一个使用默认设置的浏览器在使用默认设置的系统中有16px以外的值的例子。如果你发现了这样的例子,请分享给我。

其他回答

这篇文章很好地描述了px, em和rem的优缺点。

作者最后得出结论,最好的方法可能是同时使用px和rem,在旧的浏览器中先声明px,在新浏览器中重新声明rem:

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

pt类似于rem,因为它相对固定,但几乎总是与dpi无关,即使不兼容的浏览器以依赖于设备的方式对待px。rem随根元素的字体大小而变化,但您可以使用Sass/Compass之类的工具自动使用pt来完成此操作。

如果你有这个:

html {
    font-size: 12pt;
}

那么1rem总是12pt。Rem和em仅仅像它们所依赖的元素那样与设备无关;有些浏览器不按照spec行事,按字面意思对待px。即使在过去的网络时代,1点也一直被认为是1/72英寸——也就是说,一英寸有72个点。

如果你有一个旧的,不兼容的浏览器,你有:

html {
    font-size: 16px;
}

那么1rem是与电子器件相关的。对于默认情况下从html继承的元素,1em也依赖于设备。12pt应该是与设备无关的同等内容:16px / 96px * 72pt = 12pt,其中96px = 72pt = 1英寸。

如果你想坚持使用特定的单位,计算起来会很复杂。例如,html的.75em = .75rem = 9pt, html的.75em = .5rem = 6pt。一个很好的经验法则:

Use pt for absolute sizes. If you really need this to be dynamic relative to the root element, you're asking too much of CSS; you need a language that compiles to CSS, like Sass/SCSS. Use em for relative sizes. It's pretty handy to be able to say, "I want the margin on the left to be about the maximum width of a letter," or, "Make this element's text just a bit bigger than its surroundings." <h1> is a good element on which to use a font size in ems, since it might appear in various places, but should always be bigger than nearby text. This way, you don't have to have a separate font size for every class that's applied to h1: the font size will adapt automatically. Use px for very tiny sizes. At very small sizes, pt can get blurry in some browsers at 96 DPI, since pt and px don't quite line up. If you just want to create a thin, one-pixel border, say so. If you have a high-DPI display, this won't be obvious to you during testing, so be sure to test on a generic 96-DPI display at some point. Don't deal in subpixels to make things fancy on high-DPI displays. Some browsers might support it--particularly on high-DPI displays--but it's a no-no. Most users prefer big and clear, though the web has taught us developers otherwise. If you want to add extended detail for your users with state-of-the-art screens, you can use vector graphics (read: SVG), which you should be doing anyway.

我想赞扬josh3736的回答提供了一些优秀的历史背景。虽然这个问题已经很清楚地表达出来了,但自从这个问题被提出以来,CSS的前景在近五年内已经发生了变化。当这个问题被问到时,px是正确答案,但今天它不再成立。


Tl;dr:用rem

单位概述

历史上,px单位通常代表一个设备像素。随着设备的像素密度越来越高,这种方法不再适用于许多设备,比如苹果的Retina Display。

Rem单位代表根em大小。它是匹配root的字体大小。在HTML的情况下,它是< HTML >元素;对于SVG,它是< SVG >元素。每个浏览器的默认字体大小*是16px。

关于使用px

互联网上的大多数CSS示例都使用px值,因为它们是事实上的标准。Pt, in和其他各种单位在理论上都可以使用,但它们不能很好地处理小的值,因为你很快就需要求助于分数,这需要更长时间输入,而且很难推理。

如果你想要一个细边框,px你可以使用1px, pt你需要使用0.75pt来获得一致的结果,这不是很方便。

关于rem的使用

Rem的默认值16px并不是一个很好的使用理由。写入0.0625rem比写入0.75pt更糟糕,那么为什么有人会使用rem呢?

雷姆与其他单位相比有两方面的优势。

尊重用户偏好 你可以随意改变rem的表观px值

尊重用户偏好

多年来,浏览器缩放功能发生了很大变化。从历史上看,许多浏览器只会扩大字体大小,但当网站意识到他们漂亮的像素完美设计在任何时候都被放大或缩小时就会被破坏时,这种情况就会迅速改变。此时,浏览器会缩放整个页面,因此基于字体的缩放就不存在了。

尊重用户的意愿并不是不可能的。仅仅因为浏览器默认设置为16px,并不意味着任何用户不能将首选项更改为24px或32px以纠正低视力或低能见度(例如屏幕眩光)。如果您以rem为单位,那么任何字体大小较高的用户都会看到相应较大的站点。边界会更大,填充会更大,边际会更大,一切都将流动地扩大。

如果您的媒体查询基于rem,您还可以确保您的用户看到的网站适合他们的屏幕。如果用户在640px宽的浏览器上将字体大小设置为32px,那么在320px宽的浏览器上,用户将有效地看到以16px宽的字体显示的站点。在使用rem时,响应式网页设计(RWD)绝对没有损失。

改变表观px值

因为rem是基于:根节点的字体大小,如果你想改变1rem所代表的东西,你所要做的就是改变字体大小:

:根{ 字体大小:100 px; } 身体{ 字体大小:1快速眼动; } <p>请不要真的这样做

无论你做什么,不要将:root元素的font-size设置为px值。

如果将html上的font-size设置为px值,就会破坏用户的首选项,而无法将其返回。

如果你想改变rem的表观值,使用%单位。

这方面的数学计算相当简单。

:root的字体大小是16px,但是我们想把它改成20px。我们要做的就是用16乘以一个值得到20。

建立方程:

16 * X = 20

解出X:

X = 20 / 16
X = 1.25
X = 125%

:根{ 字体大小:125%; } 如果你使用默认的字体大小,我是20px高

用20的倍数来做所有事情并不是很好,但一个常见的建议是让rem的表观大小等于10px。神奇的数字是10/16,也就是0.625,即62.5%。

:根{ 字体大小:62.5%; } 如果你使用默认的字体大小,我是10px高

现在的问题是,页面其余部分的默认字体大小设置得太小了,但有一个简单的解决方法:使用rem设置正文的字体大小:

:根{ 字体大小:62.5%; } 身体{ 字体大小:1.6快速眼动; } 我是默认的字体大小</p>

需要注意的是,调整到位后,rem的表观值为10px,这意味着任何用px表示的值都可以通过碰撞小数位直接转换为rem。

padding: 20px;

变成

padding: 2rem;

你选择的字体大小取决于你,所以如果你想要,没有理由你不能使用:

:root {
  font-size: 6.25%;
}
body {
  font-size: 16rem;
}

让1rem等于1px。

所以你有了它,一个简单的解决方案,尊重用户的愿望,同时也避免过度复杂的CSS。

等等,这里面有什么玄机?

我就怕你会这么问。尽管我很想假装rem是魔法,可以解决所有问题,但还是有一些值得注意的问题。在我看来,这没什么大不了的,但我会把他们叫出来,这样你就不能说我没有警告过你。

媒体查询(使用em)

使用rem会遇到的第一个问题是媒体查询。考虑下面的代码:

:root {
  font-size: 1000px;
}
@media (min-width: 1rem) {
  :root {
    font-size: 1px;
  }
}

这里rem的值取决于是否应用media-query,而media查询取决于rem的值,那么到底发生了什么?

rem在媒体查询中使用font-size的初始值,并且不应该(参见Safari部分)考虑:root元素的font-size可能发生的任何变化。换句话说,它的表观值总是16px。

这有点烦人,因为这意味着您必须进行一些分数计算,但我发现大多数常见的媒体查询已经使用了16的倍数的值。

|   px | rem |
+------+-----+
|  320 |  20 |
|  480 |  30 |
|  768 |  48 |
| 1024 |  64 |
| 1200 |  75 |
| 1600 | 100 |

此外,如果你正在使用CSS预处理器,你可以使用mixin或变量来管理你的媒体查询,这将完全掩盖问题。

Safari

不幸的是,Safari有一个已知的bug,更改:root font-size实际上会更改媒体查询范围的计算rem值。如果在媒体查询中改变了:root元素的font-size,则会导致一些非常奇怪的行为。幸运的是,解决方法很简单:使用em单位进行媒体查询。

上下文切换

如果您在不同的项目之间切换,rem的表观字体大小很可能具有不同的值。在一个项目中,你可能会使用10px的表观大小,而在另一个项目中,表观大小可能是1px。这可能会让人困惑并导致问题。

在这里,我唯一的建议是坚持使用62.5%来将rem转换为10px的表观大小,因为在我的经验中,这是更常见的。

共享CSS库

如果您编写的CSS将用于您无法控制的站点,例如嵌入式小部件,那么实际上没有好方法知道rem的表观大小。如果是这种情况,可以继续使用px。

如果您仍然想使用rem,可以考虑使用一个变量发布样式表的Sass或LESS版本,以覆盖rem表观大小的缩放。


*我不想吓走任何人使用rem,但我还不能正式确认每个浏览器默认使用16px。你看,有很多浏览器,对于一个浏览器来说,稍微偏离15px或18px并不难。然而,在测试中,我还没有看到一个使用默认设置的浏览器在使用默认设置的系统中有16px以外的值的例子。如果你发现了这样的例子,请分享给我。

我发现对网站的字体大小进行编程的最好方法是为正文定义一个基本字体大小,然后对此后声明的所有其他字体大小使用em's(或rem's)。我想这是我的个人偏好,但它对我很有帮助,也让我很容易融入更具响应性的设计。

至于使用rem单元,我认为在代码的渐进性和对旧浏览器的支持之间找到一个平衡是很好的。看看这个关于浏览器支持rem单元的链接,这应该会对你的决定有很大帮助。

是的。或者,更确切地说,没有。

呃,我是说,没关系。使用对您的特定项目有意义的方法。PX和EM或两者都有效,但根据整个页面的CSS架构的不同,它们的行为会有所不同。

更新:

为了澄清,我的意思是,通常情况下,使用哪一种并不重要。有时,您可能特别希望选择其中一种。如果你可以从头开始,想要使用基本字体大小,并使所有内容都与之相关,那么EMs是很好的。

当您在现有代码基础上进行重新设计时,通常需要px,并且需要px的专一性来防止糟糕的嵌套问题。