【译】停止在 CSS 中使用像素单位

1,089 阅读8分钟

为什么 web 开发者会不假思索的使用“px”单位?这仅仅是他们的一个坏习惯?还是他们缺乏对其他 CSS 单位的认识?更或许是他们的设计团队更倾向于使用“px”和“pt”作为设计稿的单位?到目前为止,并不清楚为什么大部分的团队选择像素作为单位。

也许,大部分的原因是它看起来更加的简单方便。直觉上,我们可能认为我们是理解 “px”这个单位的,因为它看起来像在映射我们的像素屏幕。

“px”单位确实更容易让我们开始,但是,慢慢的它会暴露出来一些问题。在本文中,我将会列举三个避免使用像素单位的三个重要原因。我会探讨使用它的问题以及这些问题的对应解决方案。

1. 它们只是视觉参考单位

像素单位们已经不再基于硬件像素,在很多屏幕和分辨率下,它不会工作并且看上去也大不相同。相反的,它们基于视觉参考单位。这就导致,对于这些单位的更直观的印象不存在了。

硬件的更新日新月异,它们的像素密度也在不断的增长。我们已经不能将 96dpi 作为设备的普遍像素密度。96dpi 已经不再是一个稳定的参考值。

请注意如果基准单位是像素单位,物理单位不一定与物理侧脸相一致。如果基准单位是物理单位,则像素单位不会映射为设备像素的全部。请注意:如果像素单位和物理单位的定义与旧版本的CSS不一致,特别是,在之前版本的CSS中,像素单位和物理单位之间没有固定的比例;物理单位始终与物理测量值相关,而像素单位的变化将与参考像素最接近。(做出这个更改是因为太多的内容基于96dpi的假设,如果打破该假设会破坏内容的正确性) -W3C

总结,像素并不可靠,同时由于它的不可靠性导致不可能实现一个基于像素的完美布局。

让我们来看看不同 dpi 分辨率下 1mm 等价于多少 pixel。

MacBook下的转换

iPhone下的转换

我们已经无法根据屏幕识别像素了,尽管我们已经习惯了这种规则,但是我们必须抛弃这种想法。随着时间的推移,像素会逐渐失去它的意义,是时候停止将像素单位作为 CSS 中的默认单位了。

2. 它们是绝对值

看看上面提出的问题,为什么会出现问题?为什么无法实现完美的基于像素单位的布局?这是因为像素单位是绝对单位。意味着它无法自动适应浏览器的像素比/分辨率/大小等等。

如果你想满足广泛的使用者,绝对值是无法做到的!px 并不是唯一的绝对单位,CSS 中存在着 6 个绝对单位,如图所示:

ininches - 1in=2.54cm
cmcentimeters - 1cm=96px/2.54
mmmilimeters - 1mm = 1/10(1cm)
ptpoints - 1pt=1/72(1in)
pcpicas - 1pc=12pt
pxpixel units - 1px=0.75pt

如果你使用这些单位,就意味着使用者会看到不同的布局。在任何分辨率下测试您的页面都是不合理的。

那么,我们该如何解决这个问题?如何制作响应式布局?没错就是相对单位。相对单位是啥?

“相对长度单位是指它依赖于其它东西。可能是父元素的字体大小,或者视口的大小” — MDN Web Docs

下面是我们可以使用的相对单位

em元素的字体尺寸
ex字体尺寸的 x-height(x 字高)
cap字体吃醋的 cap-height (cap-height“大约等于大写拉丁字母的高度” )
ch等价于字符 0 (0,U+0030)的大小。
ic它是 CJK(中文/日文/韩文)表意文字的大小水(“水”,U+6C34)
rem根元素的字体尺寸
vm视口宽度的 1%
vh视口高度的 1%
vi内联方向视口的 1% (译者注:水平书写的语言(如英语))
vb块方向视口的 1% (译者注:垂直书写的语言(如日语))
vminvw 和 vh 中较小的值
vmaxvw 和 vh 中较大的值

你一定好奇为什么相对单位比绝对单位多这么多。

它们每一个都有适合使用的特定场景。正因为有这么多相对单位,我们才能更好的解决不同的场景。所以我们必须深刻的理解它们。

下面是一个例子:

如果我们希望显示一个列表,每一行最多 20 个字符。大多数的开发者是怎么做的。根据字符的字体/字型/大小计算一个字符的平均长度,然后乘以 20。

这种方法产生的是硬编码的像素值。这也就意味着如果字符的大小发生变化,不得不重新计算。这种方法只是近似值,不会在不同的设备产生一致的效果。

更好的解决方法就是使用 ch。可以将列宽设置为 ch 的 20 倍。

下面这个例子让你更好的理解。


<!DOCTYPE html>

<html>

    <head>

        <title>Units Playground</title>

        <meta charset="UTF-8" />

    </head>

    <body>

        <style type="text/css">

            body {

                color: white;

                text-align: center;

                box-sizing: content-box;

                margin: 1em;

            }

            #container {

                color: white;

                display: grid;

                gap: 1rem;

                grid-template-columns: max-content 1fr;

            }

            #content {

                padding: 1em;

                margin: 0;

                background-color: #5B2E48;

                color: white;

                max-width: 20ch;

            }

            #photo {

                background-color: #CEB992;

            }

        </style>

        <div id="container">

            <p id="content">

                Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum

            </p>

            <div id="photo">

            </div>

        </div>

    </body>

</html>

正如您所看到的,我们设置了内容的 max-width 为 20ch:


#content {

 ...

 max-width: 20ch;

}

上面仅仅是一个小例子。像素单位的替代品有很多。如果您不想使用相对的单位进行布局,也可以选择 flex 或者 grid 来进行布局。记住:不要依赖绝对单位使您的布局在不同环境下保持一致,总是选择让浏览器来帮我们完成繁重的工作。

3. 可访问性:它们不适合用户的字体尺寸

可访问性似乎是一个一直会被遗忘的主题。我们需要多关注网页的可访问性。为什么使用像素单位会影响可访问性。

浏览器默认的字体尺寸是 16px,当然我们也可以很轻易的配置默认字体尺寸。正确的字体尺寸对有视力障碍的人是非常有用的。浏览器通过设置基础的 16px 字体尺寸提示我们最适合用户的字体尺寸。

但是,当开发者使用绝对的像素值,那么浏览器的基础值则没有意义。默认的 font-size 并不会对我们的应用程序产生任何影响。所有用户看到的字体大小都相同。这是错误的,因为忽略了用户的偏好以及损坏了页面的可访问性。

我们应该如何使用字体的基础值?通过使用想 rem 和 em 这样的相对单位。什么是 rem/em?rem/em 表示相对于基本字体的字体尺寸,可以应用到盒子以及文本。简单的来说,字体尺寸最终将是基础字体尺寸的几倍。它们之间的区别是啥?

  • rem 相对于 root 的字体尺寸。

  • em 相对于元素的字体尺寸。

您不仅可以把这些单位应用到字体尺寸上,还可以应用到其它的 CSS 元素上。这意味着您可以根据用户的设置创建自适应布局。同时确保为用户提供适当的体验。

让我们看一个例子,我们将根据用户的基本字体大小调整布局。在这个例子中,我们将使用 rem 设计一个自适应布局。


<!DOCTYPE html>

<html>

    <head>

        <title>Units Playground</title>

        <meta charset="UTF-8" />

    </head>

    <body>

        <style type="text/css">

            body {

                color: white;

                text-align: center;

                box-sizing: content-box;

            }

            h1 {

                font-size: 1.9rem;

            }

            h2 {

                font-size: 1.5rem;

            }

            p {

                font-size: 1.2rem;

                color: #5B2E48;

            }

            .main-article {

                padding: 1em;

                margin: 0;

                background-color: #5B2E48;

                color: white;

                width: 30em;

            }

            .sub-article {

                padding: 1em;

                margin: 0;

                background-color: #CEB992;

                color: white;

                margin-bottom: 1em;

            }

        </style>

        <article class="main-article">

            <h1>Weather forecast for Barcelona</h1>

            <article class="sub-article">

                <h2>10 May 2021</h2>

                <p>Cloudy</p>

            </article>

            <article class="sub-article">

                <h2>11 May 2021</h2>

                <p>Sunny</p>

            </article>

            <article class="sub-article">

                <h2>12 May 2021</h2>

                <p>Sunny</p>

            </article>

        </article>

    </body>

</html>

请注意:我们在 padding,width 和 font-size 都使用了 rem。


p {

  font-size: 1.2rem;

  color: #5B2E48;

}

.main-article {

  padding: 1em;

  margin: 0;

  background-color: #5B2E48;

  color: white;

  width: 30em;

}

通过上图我们可以看到布局如何根据用户的浏览器设置。字体变大,页面也会变大。它们保持着不变的比例。尽管不同的用户看到的页面大小不一致,但是形状却还是一致的。

tips

当你使用 rem 并且设置值的时候,如果你发现默认的字体尺寸是 16px,并不利于计算,你可以采用下面的技巧来简化计算:


html {

  font-size: 62.5%; /* font-size 1em = 10px  */

}

这个技巧,是指默认的字体尺寸是 10px,你就不会被 16px 困扰。

最后的想法

我们已经阐述了为什么应该抛弃像素单位的三个强有力的理由。使用相对单位可以保证您的布局在不同的设备以及分辨率保持一致。

幸运的是,越来越多的人开始使用 rem/em。同时,浏览器也在积极地提出解决方案。使用绝对值时,如果用户缩放,浏览器将缩放来适应用户的缩放。这并不是一个完美的解决方案,仅仅是一个备选方案。