我最近在DM中收到以下信息。
我已经用HTML和CSS做了很多年了,但我仍然不知道如何实现像素完美的设计
如果你不熟悉这个术语,"像素完美 "是指你的HTML/CSS实现应该尽可能地接近原始模拟图。测量和间距应该是精确的,精确到像素。
我经常听到这种担忧;即使有多年的经验,许多前端开发人员也很难完美地再现一个设计。
当设计师把完成的模拟图交给我们时,他们相信我们会忠实地实现他们的设想。他们的工作是通过我们的实施来实现的,他们希望我们在这个过程中不要把它弄得太糟糕。*
![]()
![]()
![]()
我们究竟怎样才能生产出让我们的设计师感到自豪的东西?把一个设计复制到像素点上是否现实?为什么这么难呢?
在这篇文章中,我们将回答这些问题,并学习一些技巧来帮助我们更接近像素的完美性✨
像素-漂亮-接近
让我们先把这个问题说清楚。在严格的法律条文意义上,我认为像素完美实际上是不可能的。
我们编写的HTML和CSS将需要在令人眼花缭乱的各种设备上运行。有太多的变量会影响到一个实现的效果。
为了好玩,我截取了两个不同设备上完全相同的亚马逊清单*的屏幕截图。
使用下面的按钮在它们之间切换,看看有什么不同。
Chrome, Windows
![]()
Safari, MacOS
![]()
切换展开
当并排观看时,这两张截图看起来非常相似,但当在它们之间切换时,很明显它们并不完全相同。它们包含非常不同的像素。
当我为DigitalOcean工作时,我可以去参观他们的一个数据中心。那是一种狂野和超现实的感觉;巨大的房间里有数百排,每排有几十个机架,每排有几十台电脑。每台机器都是一样的。
我有时会嫉妒后端开发人员。后台有很多棘手的问题,不要误会我的意思,但至少他们控制着他们的代码所运行的设备!他们不需要运行在任何设备上。它不需要运行在每一个可以想象的设备上,从5英寸的手机到72英寸的电视到智能冰箱。
在上面的演示中,我只改变了两个变量。操作系统和浏览器。想一想还有多少其他因素会影响到被画的内容。
-
设备类型(台式机、笔记本电脑、平板电脑、手机、手表......)
-
屏幕大小/窗口大小
-
屏幕像素密度
-
屏幕技术(OLED、LCD、CRT、电子墨水)。
-
用户缩放级别/默认字体大小
-
性能(设备硬件、服务器负载、网络速度...)
-
设备颜色校正(如夜间模式)。
这只是我想出来的,我打赌你还有几个我漏掉的。
所以很明显,当涉及到屏幕上各个像素的RGB值时,我们将永远无法确保100%的一致性。这是一个不可能的标准。但这也不是真正的重点。
没有人要求事物在放大镜下看起来是一样的。* 大多数情况下,设计者希望实现在肉眼下看起来近乎相同,并将明显的错位和松散的间距收紧。他们希望它是像素般地接近,而不是像素般地完美。
让我们讨论一下我们如何能够做到这一点。
测量距离
当你收到一个刚出炉的模拟图时,它通常会以某种设计工具的形式交付给你,比如Figma或Zeplin。
这些工具非常棒,因为与静态图像不同,它们是设计的实时表现。你可以选择个别元素,并挑选出颜色和尺寸。
不幸的是,这些信息并不总是值得信赖的仅仅因为Zeplin告诉你标题和段落之间有64px的间隙并不意味着它是正确的。
像Sketch这样的工具从根本上说是设计工具;它们从设计领域继承了一系列的实践和特质,而且它们并不总是能整齐地映射到网络上。当然,它们会很接近,但不一定足够接近。
旧世界中的排版
如果你对设计工具中的数字为什么会不精确感兴趣,那么这段话就是为你准备的。如果你不关心,可以跳过它。
这与引导有关。在这里,"leading "与 "bedding "押韵;这个词来自于铅制的金属条。
在20世纪的大部分时间里,印刷是通过热金属排版完成的。其原理是,你会有单个字母的模具,机器会将它们排列成你想要的单词和段落。热的金属墨水被注入,然后整个东西被压在纸上,产生一个印刷品。
在这个世界上,你也会使用铅条来增加每行之间的距离。这些铅条有不同的厚度,以允许不同的距离。
![]()
问题是,无论你的铅条有多厚,第一行总是会印在同一个地方。因此,就心理模式而言,间距总是被认为是 "线下"。
这与CSS中line-height 的工作方式有细微的不同。当你增加行高时,你会在每一行周围增加垂直的填充物,在顶部和底部之间分割。
现代设计工具继承了旧世界排版的惯例,因此我们出现了一个差异。设计工具已经开始考虑这个问题,但你的情况可能有所不同。
与其相信你从设计工具中得到的测量结果,你还不如自己去测量!我最喜欢的方法是使用 "测量"。我最喜欢的方法是使用MacOS中的内置截图工具来做这件事。
你可以通过键盘快捷键cmd-shift-4 来开启这个功能。点击并拖动画一个方框,并使用右下方的数字来测量距离。如果你松开鼠标,它就会进行截图,或者你可以点击Escape 键来取消它,以避免用一堆图片弄乱你的桌面。
其他操作系统没有内置这种东西,但我已经找到了一些替代品。Greenshot(Windows)和ScreenRuler/KRuler(Linux)。
一定要同时测量模拟图和你的实现!根据需要进行调整,直到数字相同。并测量与实际字母的距离,而不是它们周围的一些假想框
努力发现差异:安排好你的窗口,让模型和你的实现并排在一起,并寻找细微的差别。把它当作一个发现差异的游戏。
还有一些工具,如PixelSnap。PixelSnap是一个工具,它可以让你快速、轻松地测量屏幕上的所有东西,使用一堆先进的工具。它是付费软件,但你也许可以说服你的雇主为团队购买一些许可证
设计系统
组织采用设计系统正变得越来越普遍。一个设计系统是一套令牌、常量和组件,形成一个有凝聚力的系统,供设计和工程使用。
在一个理想的世界里,你永远不需要测量任何东西,因为间距会被标记化。设计师可以说 "这个间隙是一个4级空间",这将对应于你的主题中的一些像素数。
在实践中,这并没有解决设计工具和网络之间的一些差异。我曾经使用过很多设计系统,但我仍然发现自己在做一些小的调整。
设计系统提供了一个很好的基础,但在我看来,它们并没有完全解决这个问题。
多走一步路
看一下下面这两个圆圈。你认为哪个是正确的居中?
第二个看起来更好,不是吗?然而,第一个在技术上是正确的答案。
在CSS中,所有东西都是方框。数字 "1 "在它周围产生了一个方框,这个方框是完全居中的。
右边的那个已经被移位了,所以它的茎与垂直轴对齐。
这就是所谓的光学对齐。它是根据人的感觉来排列的,而不是根据盒子之间的绝对数学距离来排列的。
诚然,这是一个非常小的细节,如果数字是数据驱动的,它就变得不切实际。但这是一个很好的例子,说明数学上的居中并不总是感觉正确。有时,我们需要做一些小的调整,使我们的眼睛相信事物是正确对齐的。
我经常发现自己需要做这样的轻微转变。让我们看看另一个例子。在这两个选项之间进行切换,看看哪一个对你来说感觉更好。
你好,世界
这是一个标题下面的段落。这一段有很多字,你可以想象它有非常重要的东西
拨动
如果我们使用元素检查器,我们会发现内容框在排版的左边缘之前包括几个像素的死角。
![]()
令人高兴的是,导致这一空白的字符间距在不同的浏览器渲染引擎中似乎是一致的,因此我们可以安全地将东西移开几个像素,以达到普遍改善的对齐效果。
说白了,我知道这是很微妙的。你可以在不做这种光学对准的情况下实现非常清晰的设计。我们是在 "最后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是一种具有欺骗性的复杂语言。相对来说,它很容易上手,可以调整排版样式和移动东西。但现实世界的项目从来都不是那么简单的,事情很快就会变得复杂。