在网络中充满了资源告诉你用相对长度em
和rem
来代替像素,因为它们会使你的设计更容易。几乎我所知道的所有的前端工程师(包括我自己)多年来都盲目的追随这些指示,这在行业中也变成了一个约定俗成的标准。最近我做了一些调查研究,完全改变了我对这两个相对单位的看法。从现在开始我将不会再使用rem
并且只会在非常特殊的用例中才会使用em
。在这篇文章中我将分享我的观察结果,希望可以说服你结束我们挚爱的rem
单位,最终没有回退的使它进入我们的工具(鉴于IE8死的慢),但是变得毫无用处支持更受欢迎的CSS参考像素。
em
单位在排版中有它的起源,em
是作为给定类型字体大小的相对大小。在过去,打印都是关于凸版印刷排版,用金属将信印在纸上所以被叫做空铅(最初的嵌块)。这些空铅都有相同的高度,可以适合给定大小和类型的字母表中的每一个字母。然而,他们有不同的宽度,因为大写的字母“M”在宽度和高度上接近相等,所以约定俗成的将"M"的宽度作为相对单位建立。因此em
单位名的起源只是因为这个是字母"M"的语音表达(ɛm)(我找不到对这个起源的任何历史证明,但是人们似乎认为这是最合理的解释)。
电脑都是关于像素的,在1996年在CSS1中引入em
长度时,主要目的是引入一种相对于给定上下文的字体大小的单位。规范中说到:
相对单位
em
和ex
是相对于元素本身的字体大小的。在CSS1中唯一的例外是font-size
属性,它的em
和ex
值指的是父元素的字体大小。
在开始的时候em
是一个对CSS很好的增加,它允许建立一个对你的内容敏感的设计。你可以相对于父元素来设置子元素的文本大小,或者做一些事情像用em
来指定你的内边距来确保在你的文本容器中有一个比你的字间距更大的内边距。(符合邻近的视觉规律)
另一个用例,是em
变得非常受欢迎的主要原因,就是可访问性原因。它的相对于DOM的根节点的性质(接下来下面将提到其约束)使它完美的根据用户偏好调整你整个设计的尺寸。浏览器支持改变默认的字体大小从而改变你整个网站中em
的计算结果。
但是em
有一个相当大的缺点。像在规范中列出的,它是继承的,如果你有多个嵌套的元素重载em
的字体大小,每次你想计算DOM中深层的节点的字体大小的时候,你都需要经过很多数学运算。
让我们通过观察下面的代码片段来快速的说明这个问题:
<div class="level-1">
<div class="level-2">
<div class="level-3">
<p>Hello!</p>
</div>
</div>
</div>
html {
font-size: 20px;
}
.level-1, .level-2 {
font-size: 0.5em;
}
.level-3 {
font-size: 2em;
}
你觉得“Hello”文本的字体大小是多少呢?因为em
的值随着DOM的级联和嵌套变化,所以真的很难跟踪发生了什么。在这个例子中,文本的字体大小是10px
,因为html元素最初的20px
在乘以2
之前乘了两次0.5
。
REM,相对单位的超级英雄 !
最后,用CSS3解决上面的问题。REM表示“Root EM”,字面上指的是根元素的em
大小。在Web文档的上下文中,根元素就是你的html元素。
这个简直太奇妙了!我们可以方便的使用相对字体大小,而且还避免了使用嵌套的em
结构的混乱。几乎每一个开发人员接受这个新的、奇特的CSS长度单位,它变得非常受欢迎。
唯一的问题是缺少IE8的支持。自2005年CSS3的第二稿以来,REM没有被认为重要的足以包括在四年以后发布的IE8中。不管怎样,正如我们知道如何解决IE的问题一样,我们开始使用REM的像素后退模式。
.my-text {
font-size: 32px;
font-size: 2rem;
}
CSS是温和的,它总是建立在优雅降级的概念上。如果渲染引擎不理解一个属性或者值,它只是忽略它。这使得现代浏览器支持用rem
指定属性,而老的浏览器只是忽略后面用rem
指定属性的那行。
移动时代
今天我们生活在一个移动时代,这从两端改变了互联网,我们如何使用它以及我们如何建立它。响应式网页设计变得非常流行,并且可能是最常用的专业术语。虽然在2010年媒体查询模块已经被Håkon Wium Lie具体说明,但它加入到CSS3规范中是在相对较晚的工作草案8中,同时这也是最后使用的工作草案。
现今每个前端工程师意识到媒体查询是一个很有用的东西,在某种程度上我们几乎在每个项目中都用到它。在媒体查询变得流行,人们开始为移动设备设计他们的网站之后没多久开始了一些争论,关于使用像素还是相对字体单位rem
或em
来指定媒体查询。让我们来看看Zurb在2011年十月发布的响应式CSS框架Foundation2:
/* Mobile */
@media only screen and (max-width: 767px) {}
/* Modernizr-enabled tablet targeting */
@media only screen and (max-width: 1280px) and (min-width: 768px) {}
你可以看到768px-1280px
是用于桌面宽屏(PC宽屏),768px
以下的是用于移动宽屏(手机宽屏)。
你还可以观察到,像素单位被用来指定媒体查询。让我们来看看Foundation更新的版本。Foundation 5是移动优先的,并且基于媒体查询的所有屏幕尺寸都是用em
为单位的。
/* xs up */
@media only screen {}
/* small up */
@media only screen and (min-width: 40.063em) {}
/* medium up */
@media only screen and (min-width: 64.063em) {}
/* large up */
@media only screen and (min-width: 90.063em) {}
/* xlarge up */
@media only screen and (min-width: 120.063em) {}
如果我们假定浏览器默认的字体大小是16px
,基于这个大小来计算我们的em
,那么这些媒体查询的计算结果分别是640px
,1024px
,1440px
,1920px
。
乍一看,这非常有意义,因为现在我们有了基于根元素字体大小的媒体查询,这意味着我们的媒体查询是按照浏览器字体大小按比例缩放的。然而,在结论部分你将发现在媒体查询中用em
或者rem
会有大量的问题。
高DPI的提高
多年前,屏幕上的像素是你可以很容易在一定距离远的17英寸分辨率为1024x768
的显示器上认出来的笨拙的大正方形。随着屏幕分辨率的增加和与高清视频的协调,不再仅仅是关于分辨率了。很明显,大分辨率下的用户界面很难像在非常小的屏幕下那样处理。
为了处理这个问题,操作系统和软件用户界面引进了一个比例要素(在网站开发中被称为设备像素比),在软件中它将被用来计算一个虚拟像素。你可以想象,用户界面实际上比正常大小显示的更大。如今大多数现代的智能手机至少有2
的设备像素比,这意味着在物理宽度上它们不是320px
而是640px
。尽管如此,你的手机操作系统知道它需要将每个元素元素渲染为原来的两倍大来补偿你的观察。像物理像素或者设备分辨率指的是在设备中可用的实际像素量,而虚拟尺寸经常归类为逻辑分辨率。
在CSS中这个问题实际上早在1996就已经在1.0版本中被提到。下面引用了W3C的CSS1规范中介绍CSS参考像素角度。
当被用于最后的规则时,像素单元是相对于画布的分辨率的,即最常见的电脑显示器。如果输出设备的像素密度与一个典型的计算机显示器非常的不同,那么终端应该重新调整像素值。建议的参考像素是在一个设备上一个像素的视觉角度,这个设备有90bpi的像素密度并且与读者有一定的距离。对于28英寸的距离,视觉角度大约为0.0227度。
这是我第二次惊讶于Opera技术人员在CSS1规范发布时就具有的技术洞察力。第一次是惊讶于他们对媒体查询的洞察力,在CSS1中他们就已经将关于@media
的内容在规范记下来了。
HTML未来的版本可能会引入新的值,可能允许参数化的值。为了促进这些扩展的引入,终端必须能够按照下面这样解析媒体属性值:值是以逗号分隔的条目。例如,
media=”screen, 3d-glasses, print and resolution > 90dpi
。
这个是1996年时被人记下来的!他们可能遇到了来自"Back to the Future"的"Doc" Brown然后告诉他们关于Oculus Rift的内容…
那么太好了!我们有可以按比例缩放用户界面的操作系统和利用参考像素来按比例缩放网站内容的网站。为什么我告诉你这一切!?
可访问性和现代浏览器的真相
为了理解rem
单位的必要性我们需要回到过去。我所说的回到过去是指桌面屏幕分辨率大约为1024px
宽,我们首选的浏览器为IE6的时候。那个时候我们首选的网站字体是10px
大小的Tahoma或者Verdana。不开玩笑,这是最先进的,如果你碰巧没有机会去享受这个!
在那时提高弱视人群的可访问性的最常用的的方法就是按比例放大你的网站的文本大小。在IE中,你可以在你的视图设置中改变你的文本大小从正常到大或者更大。这直接改变了从html元素继承来的浏览器默认字体大小(在IE6中为12pt
。当时我们用em
来设置我们的内容的样式,所以如果一个有障碍的人改变默认的字体大小,将会让整个网页立即按比例缩放。
然而,那是2001年的时候。现在设备,浏览器和操作系统都已经变化发展了。
当rem
单位来解决使用em
带来的问题的时候,它也变得不重要,因为现在我们已经有一个广泛采用的用户很容易控制的参考像素。新的有魔力的技术是简单缩放。在2006年十月发布的IE7中,浏览器窗口的右下角有一个非常突出的缩放图标。猜猜会怎样...这个缩放功能只是修改浏览器CSS渲染引擎的CSS参考像素!这是多么大的突破!下面展示一下来自旧版本浏览器的截图,上面有一些关于它们如何处理这个特定的访问性问题的注释。
IE6(2001)只允许文本缩放(改变浏览器根元素的默认字体大小),因此是一个rem
和em
都有意义的浏览器。
IE7(2006)和IE8支持改变用户界面的参考像素的缩放,在视图菜单上进行文本缩放是可能的。
IE9(2011)-IE11,缩放和改变文本大小都在视图菜单中,很更支持明显缩放,因为菜单中显示了当前的缩放比例并且是位于文本大小的上面。
Safari 4 (2009),在视图菜单中有缩放,但是不是很支持改变文本大小。
Firefox 3 (2008),默认为缩放,文本大小改变没有直观的在菜单中。
Chrome 14 (2011),默认为缩放,文本大小改变在设置菜单中被隐藏。
正如我们所看到的,即使是很古老的浏览器都不再支持用户改变默认字体大小。它们更支持缩放功能(CSS参考像素)。这绝对是有意义的。如果你改变参考像素的大小,你就改变了整个页面,让每个东西都更大了,不仅仅是用rem
和em
指定的长度。
另一个可访问性的事实是,系统范围的设置可以反映到应用程序中。一个有障碍的人最可能长久改变他的操作系统访问设置。在Windows系统中,用户可以将他的DPI扩展设置改变到100%以上,这非常类似于浏览器中的CSS参考像素。这可以使操作系统在可能的情况下缩放对象和用户界面。它也通知应用程序增加DPI比例系数。猜猜会发生什么?浏览器将会用这个DPI比例系数来影响CSS参考像素,所以看起来像有一个默认的缩放应用在浏览器中。这又是一个"rem"被错误的赞扬为一个可访问性英雄的原因。
结论
如果你还在用rem
和em
来达到可访问性的目的,请马上停止使用它们!它们是完全不直观的,只是介绍了另一个不再需要的抽象级别。你永远不能确定根元素的字体大小是多少,为了得到有关的东西(像素)你必须做一些数学运算。
我们一直关注像素,这就是我们如何处理图像和用户界面。我们很快将生活在一个DPI独立的世界,虚拟像素和逻辑屏幕分辨率将会成为我们需要关心的一切,对于网站来说自从2006年以来这就已经成真了(如果浏览器更早的被采用这甚至会更早)。
所以请帮自己一个忙,丢弃你的"rem"长度,使用像素吧。如今的最佳实践是使用缩放功能如果你的视力受损,由于现代浏览器的推广和设置这也是显而易见的。这将改变CSS参考像素,整个页面将会被缩放,包括你的像素长度,em
,rem
和其它任何东西。
对于在媒体查询中使用rem
和em
,我是完全反对的,并且发现这个是更不直观的。这里存在的问题是,rem
以及em
不是参考根元素(html)而是直接参考浏览器的默认字体大小,这个是只能通过浏览器的基本字体大小设置来改变的(在现代浏览器中这个是隐藏在高级设置中的)。这个意味着即使你给你的html元素指定了30px
的字体大小,媒体查询中的em
/rem
将依旧使用16px
作为参考,除非你在浏览器设置中也改变了你的默认字体大小。
当缩放一个页面和改变CSS参考像素的时候,用像素指定的媒体查询也会用参考像素来计算实际的像素数量。知道这点也很重要。如果你在媒体查询中使用设备宽度情况就不是这样,媒体查询将参考物理像素而不考虑CSS参考像素。然而,在设备宽度应该代替宽度(或者是最小宽度/最大宽度)被使用这点上我没有看到令人信服的理由。
为了做一些试验和进行跨浏览器的检查,我在JSBin上创建了http://output.jsbin.com/fesoba。你可以看到当进行缩放的时候,用像素指定的媒体查询和用"rem"指定的媒体查询的行为是一样的。
一些非常特定的用例中使用em
实际上仍然是有意义的。如果你想对一个组件的字体大小使用相对长度,从视觉角度来看,em
完全有意义。但是对于rem
我实在找不到一个有效的用例。如果你能证明我错了,我很乐意听到你的意见。
本文根据@Gion Kunz的《R.I.P. REM, Viva CSS Reference Pixel!》所译,整个译文带有我们自己的理解与思想,如果译得不好或有不对之处还请同行朋友指点。如需转载此译文,需注明英文出处:https://mindtheshift.wordpress.com/2015/04/02/r-i-p-rem-viva-css-reference-pixel/。
如需转载,烦请注明出处:http://www.w3cplus.com/css/r-i-p-rem-viva-css-reference-pixel.html