你是否思考过对于媒体查询你应该使用px,em还是rem?我也产生过同样的问题,并且目前为止,我还是没有明确的答案。
一年之前,我第一次创建 mappy-breakpoint 仓库时,我一直使用rem单位。之后一次和Sam Richard谈话之后,我开始转向使用em,因为我并没有发现两者之间的区别。
关于媒体查询,除了em和rem,常用单位还有像素。自从现在所有浏览器存在像素缩放问题,我想知道像素是否还可以用于媒体查询。
这周,我打算弄明白两者之间的区别。
在开始这篇文章之前,我假设你已经知道了什么是em和rem单位。如果你不知道的话,请查阅这篇文章。
基础实验
我想创建三个独立的<div>元素,一个用于px,一个用于em,一个用于rem。我给每个<div>元素添加一个背景色,便于区分。
.pixel { background: red; } .em { background: green; } .rem { background: blue; }
接下来,因为我们比较媒体查询单位,我在三个选择器上创建了一个min-width。
当媒体查询被触发时,我决定降低元素的不透明度,这样我就可以立即看到他们之间的差异。下面是像素媒体查询的 CSS 样式:
.pixel { background: red; @media (min-width: 400px) { opacity: 0.5 } }
接下来,我们就要弄清楚如何创建em和rem单位。
在第一次实验中,如果所有条件都理想的话,我想要测试三个单位之间的差异。换句话说,没有以下情况下发生:
- 在<html>中更改font-size。
- 用户放大。
- 用户更改浏览器字体设置。
如果已经满足了以上理想的条件,我就可以想当然认为的16px == 1em == 1rem。那么 400px就等于25em或25rem.
.pixel { background: red; @media (min-width: 400px) { opacity: 0.5 } } .em { background: green; // 400 ÷ 16 = 25 @media (min-width: 25em) { opacity: 0.5 } } .rem { background: blue; // 400 ÷ 16 = 25 @media (min-width: 25rem) { opacity: 0.5 } }
如果三个媒体查询以相同的方式进行,我们应该就可以看到他们都准确的在 400px 触发。
结果如下(我在每一个浏览器所测试的)。
因为三个媒体查询在相同的断点处被触发,所以我们知道,这一阶段px, em或rem之间并无差异.
建立基础实验后, 下一步是要测试在缺少以上理想条件的情况下,会出现什么情况。同样的,条件为:
- 在<html>中更改font-size。
- 用户放大。
- 用户更改浏览器字体设置。
让我们一个一个的去测试。
在HTML中更改Font-size
第一种情况是很普遍的。事实上,几乎所有的网页使用此方法在CSS中设置font-size默认值:
html { // setting default font size font-size: 200% }
这里,我在测试中选择将font-size设置为200%,这意味着我将1em和1rem设置为了32px.如果em和rem受font-size改变的影响,他们将会在800px被触发。
如下是测试结果:所有的媒体查询在Chrome, Firefox 和 IE 11浏览器下均在400px被触发。
这是正确的表现行为。em和rem单位在HTML中不应受font-size的变化影响,因为他们是基于浏览器内部的font-size属性。
不幸的是,我们没在 Safari 上得到此完美的行为。它在800px时触发了rem媒体查询:(
因为这种行为只发生在 Safari 浏览器中,我很想看看是否移动端 Safari也会出现此情况。实验证明,也会出现此现象。
所以,第一个场景已经证明,我们不应该使用rem媒体查询。然而,让我们继续把 rem 放在我们其余的实验中,看看是否会发生其他的事情。
用户放大
第二种情况也是十分常见的。如果你页面上的文本不足够大,用户可能会选择使用他们浏览器中内置的缩放功能来放大文本。
一个简短的说明:最初关于em的想法是因为当用户放大时,旧浏览器不能够更新像素值。在这方面,测试媒体查询单位时缩放将有助于回答这个问题,我们是否可以现在使用基于px的媒体查询。
这个实验结果显示,Chrome,Firefox 和 IE 显示相同的行为。px单位查询在em和rem查询时被同时触发。
哈哈,你猜对了…Safari并不支持:(
不幸的是,这意味着基于像素的媒体查询是不存在问题的。Safari浏览器不支持他们(除非你决定放弃 Safari?)。
现在,我们进行最后的实验,看看是否仍然会发生什么意外。
用户更改浏览器的Font值
许多开发商愿意相信,用户不会改变他们浏览器font-size的值,因为他们已经隐藏在 deeeep 的设置之中。
恩恩,如果这样子的话后果会很棒,因为所有用户都表示出此行为,我们就不需要做这个实验!:)
不幸的是,并没有数据证明用户不更改他们浏览器的font-sizes属性值,所以作为开发人员,我们仍然有责任考虑到我们网站的灵活性。
在这个实验中,我扩大了四个浏览器中的font-size属性值,并通过以下方式进行测试(如果你想跟随):
- Chrome: 前往settings, show advanced settings, web-content.
- Firefox: 前往preferences, content, fonts 和 colors.
- Internet Explorer: 在page单击, 之后 text-size.
我想不出在何处设置字体大小的唯一浏览器是Safari。所以我用代理服务器代替。例如,我将最小的字体大小更改为大于16px的设置。如果你也要这样做,请转到preferences, advanced, acessibility.
这是唯一所有浏览器表现行为一致的测试:
正如你所看到的,像素查询的触发要早于em或rem查询。
这里没有出现任何bug。由于 px 是绝对单位,就会正确的执行。无论用户如何更改他们默认的font-size属性值,断点应维持在 400px处。
另一方面,em和rem基于浏览器的font-size属性值。因此,当用户更改默认值时,应该更新其媒体查询的font-size设置。
所以,这里对于像素的痴迷者,我很抱歉打破你的泡沫幻想,但基于像素查询是行不通。
实验总结
正如你可以从上面实验中看出,在四个浏览器之间表现一致的唯一单位是em。除了em和rem在 Safari 上发现的bug之外,其并不存在任何差异。
px媒体查询在三次实验的两次中均表现正常(再一次,除了Safari)。不幸的是,在第三个实验中,当用户更改默认的浏览器font-size值时,px媒体查询仍在400px被触发。
因此,我在这些实验后得出的结论是:使用em媒体查询.
如果您正在使用一个没有使用em媒体查询的库时,你应该让其开发人员查看这篇文章,让他们知道他们的代码影响。不然,可以参考基于em的Mappy-breakpoints, Breakpoint-sass 或者 sass-mq 库。
本文根据@Zell的《PX, EM or REM Media Queries?》所译,整个译文带有我们自己的理解与思想,如果译得不好或有不对之处还请同行朋友指点。如需转载此译文,需注明英文出处:http://zellwk.com/blog/media-query-units/。