HTML和CSS:如何追逐完美像素

154 阅读10分钟

我最近在DM中收到以下信息。

我已经用HTML和CSS做了很多年了,但我仍然不知道如何实现像素完美的设计

如果你不熟悉这个术语,"像素完美 "是指你的HTML/CSS实现应该尽可能地接近原始模拟图。测量和间距应该是精确的,精确到像素。

我经常听到这种担忧;即使有多年的经验,许多前端开发人员也很难完美地再现一个设计。

当设计师把完成的模拟图交给我们时,他们相信我们会忠实地实现他们的设想。他们的工作是通过我们的实施来实现的,他们希望我们在这个过程中不要把它弄得太糟糕。*

我们究竟怎样才能生产出让我们的设计师感到自豪的东西?把一个设计复制到像素点上是否现实?为什么这么难呢?

在这篇文章中,我们将回答这些问题,并学习一些技巧来帮助我们更接近像素的完美性✨

像素-漂亮-接近

让我们先把这个问题说清楚。在严格的法律条文意义上,我认为像素完美实际上是不可能的。

我们编写的HTML和CSS将需要在令人眼花缭乱的各种设备上运行。有太多的变量会影响到一个实现的效果。

为了好玩,我截取了两个不同设备上完全相同的亚马逊清单*的屏幕截图。

使用下面的按钮在它们之间切换,看看有什么不同。

Chrome, Windows

A screenshot of an Amazon listing, taken on a Windows 10 PC running Chrome

Safari, MacOS

A screenshot of an Amazon listing, taken on an iMac Pro running Safari

切换展开

当并排观看时,这两张截图看起来非常相似,但当在它们之间切换时,很明显它们并不完全相同。它们包含非常不同的像素。

当我为DigitalOcean工作时,我可以去参观他们的一个数据中心。那是一种狂野和超现实的感觉;巨大的房间里有数百排,每排有几十个机架,每排有几十台电脑。每台机器都是一样的。

我有时会嫉妒后端开发人员。后台有很多棘手的问题,不要误会我的意思,但至少他们控制着他们的代码所运行的设备!他们不需要运行在任何设备上。它不需要运行在每一个可以想象的设备上,从5英寸的手机到72英寸的电视到智能冰箱。

在上面的演示中,我只改变了两个变量。操作系统和浏览器。想一想还有多少其他因素会影响到被画的内容。

  • 设备类型(台式机、笔记本电脑、平板电脑、手机、手表......)

  • 屏幕大小/窗口大小

  • 屏幕像素密度

  • 屏幕技术(OLED、LCD、CRT、电子墨水)。

  • 用户缩放级别/默认字体大小

  • 性能(设备硬件、服务器负载、网络速度...)

  • 设备颜色校正(如夜间模式)。

这只是我想出来的,我打赌你还有几个我漏掉的。

所以很明显,当涉及到屏幕上各个像素的RGB值时,我们将永远无法确保100%的一致性。这是一个不可能的标准。但这也不是真正的重点。

没有人要求事物在放大镜下看起来是一样的。* 大多数情况下,设计者希望实现在肉眼下看起来近乎相同,并将明显的错位和松散的间距收紧。他们希望它是像素般地接近,而不是像素般地完美。

让我们讨论一下我们如何能够做到这一点。

测量距离

当你收到一个刚出炉的模拟图时,它通常会以某种设计工具的形式交付给你,比如Figma或Zeplin。

这些工具非常棒,因为与静态图像不同,它们是设计的实时表现。你可以选择个别元素,并挑选出颜色和尺寸。

不幸的是,这些信息并不总是值得信赖的仅仅因为Zeplin告诉你标题和段落之间有64px的间隙并不意味着它是正确的。

像Sketch这样的工具从根本上说是设计工具;它们从设计领域继承了一系列的实践和特质,而且它们并不总是能整齐地映射到网络上。当然,它们会很接近,但不一定足够接近。

旧世界中的排版

如果你对设计工具中的数字为什么会不精确感兴趣,那么这段话就是为你准备的。如果你不关心,可以跳过它。

这与引导有关。在这里,"leading "与 "bedding "押韵;这个词来自于铅制的金属条。

在20世纪的大部分时间里,印刷是通过热金属排版完成的。其原理是,你会有单个字母的模具,机器会将它们排列成你想要的单词和段落。热的金属墨水被注入,然后整个东西被压在纸上,产生一个印刷品。

在这个世界上,你也会使用铅条来增加每行之间的距离。这些铅条有不同的厚度,以允许不同的距离。

A bunch of strips of metal, each with different thicknesses

问题是,无论你的铅条有多厚,第一行总是会印在同一个地方。因此,就心理模式而言,间距总是被认为是 "线下"。

这与CSS中line-height 的工作方式有细微的不同。当你增加行高时,你会在每一行周围增加垂直的填充物,在顶部和底部之间分割。

现代设计工具继承了旧世界排版的惯例,因此我们出现了一个差异。设计工具已经开始考虑这个问题,但你的情况可能有所不同。

与其相信你从设计工具中得到的测量结果,你还不如自己去测量!我最喜欢的方法是使用 "测量"。我最喜欢的方法是使用MacOS中的内置截图工具来做这件事。

你可以通过键盘快捷键cmd-shift-4 来开启这个功能。点击并拖动画一个方框,并使用右下方的数字来测量距离。如果你松开鼠标,它就会进行截图,或者你可以点击Escape 键来取消它,以避免用一堆图片弄乱你的桌面。

其他操作系统没有内置这种东西,但我已经找到了一些替代品。Greenshot(Windows)和ScreenRuler/KRuler(Linux)。

一定要同时测量模拟图和你的实现!根据需要进行调整,直到数字相同。并测量与实际字母的距离,而不是它们周围的一些假想框

努力发现差异:安排好你的窗口,让模型和你的实现并排在一起,并寻找细微的差别。把它当作一个发现差异的游戏。

还有一些工具,如PixelSnap。PixelSnap是一个工具,它可以让你快速、轻松地测量屏幕上的所有东西,使用一堆先进的工具。它是付费软件,但你也许可以说服你的雇主为团队购买一些许可证

设计系统

组织采用设计系统正变得越来越普遍。一个设计系统是一套令牌、常量和组件,形成一个有凝聚力的系统,供设计和工程使用。

在一个理想的世界里,你永远不需要测量任何东西,因为间距会被标记化。设计师可以说 "这个间隙是一个4级空间",这将对应于你的主题中的一些像素数。

在实践中,这并没有解决设计工具和网络之间的一些差异。我曾经使用过很多设计系统,但我仍然发现自己在做一些小的调整。

设计系统提供了一个很好的基础,但在我看来,它们并没有完全解决这个问题。

多走一步路

看一下下面这两个圆圈。你认为哪个是正确的居中?

Two blue circles each contained the number one. One is centered mathematically, the other is tweaked to appear more aligned

第二个看起来更好,不是吗?然而,第一个在技术上是正确的答案。

在CSS中,所有东西都是方框。数字 "1 "在它周围产生了一个方框,这个方框是完全居中的。

右边的那个已经被移位了,所以它的茎与垂直轴对齐。

The same two circles, except now there are markers. Two pink lines are drawn along on both axes.

这就是所谓的光学对齐。它是根据人的感觉来排列的,而不是根据盒子之间的绝对数学距离来排列的。

诚然,这是一个非常小的细节,如果数字是数据驱动的,它就变得不切实际。但这是一个很好的例子,说明数学上的居中并不总是感觉正确。有时,我们需要做一些小的调整,使我们的眼睛相信事物是正确对齐的。

我经常发现自己需要做这样的轻微转变。让我们看看另一个例子。在这两个选项之间进行切换,看看哪一个对你来说感觉更好。

你好,世界

这是一个标题下面的段落。这一段有很多字,你可以想象它有非常重要的东西

拨动

如果我们使用元素检查器,我们会发现内容框在排版的左边缘之前包括几个像素的死角。

A zoomed-in screenshot of the above demo, with a blue box showing the "content box" around the typography

令人高兴的是,导致这一空白的字符间距在不同的浏览器渲染引擎中似乎是一致的,因此我们可以安全地将东西移开几个像素,以达到普遍改善的对齐效果。

说白了,我知道这是很微妙的。你可以在不做这种光学对准的情况下实现非常清晰的设计。我们是在 "最后5%"的领域。但是,这确实有区别,对于关键性的页面(主页、高流量的登陆页面)来说,花几分钟时间进行这些调整是值得的

阴晴不定的组件

你可能已经注意到本文的一个模式:很多小的调整,使事情感觉正确。

不断地改变事物会让人感觉很混乱。为了增加一点约束,并确保使用一致的策略,我喜欢为自己创建一个小小的React组件。下面是它的样子。

function ShiftBy({ x = 0, y = 0, children, ...delegated }) {
  return (
    <div
      {...delegated}
      style={{
        transform: `translate(${x}px, ${y}px)`,
      }}
    >
      {children}
    </div>
  );
}

下面是它的使用方法。

<section>
  <ShiftBy x={-3}>
    <Heading>Hello world</Heading>
  </ShiftBy>
  <p>This is a paragraph below a heading</p>
</section>

即使你不熟悉React,希望这个片段能让你感觉到它在做什么。我们的ShiftBy 组件允许我们沿着任一轴线移动一些像素。

我喜欢这一点,因为它的意图非常清楚;我们正在进行细微的调整,以使事物感觉良好的对齐。我们不是在一堆预先存在的元素上随意地撒上一些CSS,似乎是随意地撒。

transform: translate 这是我所知道的转移东西的最不具侵略性的方法。与使用边距不同,它不会把兄弟姐妹也拉进来。

你会惊讶于这个组件经常派上用场。例如,我对我的无序列表中的自定义子弹做了少量的移动。

  • 项目1

  • 项目2

把它们对准中心或基线感觉不太对,所以我把它们调整了几个像素,直到它们与我的眼睛相吻合。

对CSS充满信心

CSS是一种具有欺骗性的复杂语言。相对来说,它很容易上手,可以调整排版样式和移动东西。但现实世界的项目从来都不是那么简单的,事情很快就会变得复杂。