The problem with ‘pixel perfect’ design
Pixel perfect design worked well for about 100 years. But in 2025, with every screen being a different size and the ever growing need for accessibility, we need something better. In this talk, Craig will cover the pitfalls of using static measurements, and why designing in systems and math rooted in musical theory may be a better approach.
Craig Abbott
Craig is a Principal Accessibility Consultant at TetraLogical and the former Head of Accessibility at the Department for Work and Pensions. He is passionate about neurodiversity, and is an advocate of accessibility that goes beyond just compliance.
Links
Video Permalink ¶
Transcript
Hi everyone. So yeah, I'm Craig. I'm a principal accessibility consultant at TetraLogical. Before
we start, I always like to just let everyone know that I have ADHD and I'm also autistic.
So depending on which side wins, the talk will either end up super clinical or like
super erratic. And I've got a lot to get through, so hopefully the ADHD wins. But yeah, I think
also as well, just to point out, when I was talking on the way in about what I'm about
to talk about, I think given the people who are in the room, I think, you know, hopefully
this will just be stuff that you already know. But then thankfully Matt did a talk all about
stuff that you already know, so I'm just going to ride with that. But yeah, I want to talk
a little bit about pixel perfect design. I've worked in a few organizations where this is
a thing still where designers get really hung up on everything being pixel perfect and everything
being exactly in the browser as it is in the Figma file and whatnot. And I find it a bit
bizarre that this is still a thing in, you know, 2025. So pixel perfect, basically just
making whatever's in the browser and whatever's in the Figma file or whatever design file
they're using just look absolutely identical. I mean, I've literally seen a designer screenshot
the browser and overlay it in a Figma file and be like, this is 10 pixels out or something.
And really only designers care if something's not pixel perfect. Users don't care, developers
don't care, product managers don't care, but we spend ages making it look pretty and we
want the final design to reflect our expertise. So often designers are the ones that are the
ones pushing it. But pixel perfect does cause headaches for developers. I lost my water.
Yeah, so developers with pixel perfect design, we find they write more CSS, they're often
having to use override utility classes or write custom CSS to override things that are
already there. The company that I previously worked at, we had a design system and there
was just loads of like inline styling being put on the components just to make everything
look exactly as the designer wanted it to look. And that creates inconsistencies and
it creates headaches for developers. But pixel perfect is an interesting term because perfect
is really subjective. Different designers have different opinions on how wide a margin
should be. If you ask the same designer on different days, they can have different opinions.
So like the term perfect is really subjective. So I think also when we talk about pixels,
yeah, so this again caveat I suppose for this talk is that I find a lot of designers don't
necessarily understand pixels. We often think that a pixel is a pixel on a screen like a
tiny square or something. I'm assuming everybody in this room knows what I'm about to talk
about. But yeah, so pixels are basically picture elements. So if we take a picture or pix and
then we take elements and Ls, we end up with pixels. The digital pixel is the smallest
element of a digital picture. So if we take this awesome picture of a cat and we zoom
in in Photoshop or Figma or whatever it is and we keep zooming in, we eventually get
to a pixel which is the smallest element of the image which is a solid block of color.
Then we have physical pixels which are the smallest element on a modern display. So again
if we took a nice picture of a cat on a monitor and we zoomed in and zoomed in and zoomed
in, we eventually get to a red, green, blue pixel element. And this worked really well
for about 80 or 90 years because all screens use the same 4 by 3 ratio and there was roughly
a 1 to 1 mapping. So when they were firing electrons at the screen, you know the RGB
area was roughly a 1 to 1 mapping. So everything kind of just worked. Content just scaled up
and down. It didn't need to adapt. It didn't need a reflow. It didn't need to do anything.
If you put it on a small telly or a big telly, it just looked the same but bigger. But these
days screens are not consistent. So we've got different dimensions, we've got different
aspect ratios, and we've got different pixel densities. Physical pixel densities I suppose
it should clarify. And then to complicate Matt as further, we have CSS pixels which
are abstract units which are calculated by the browser. And these can be made up of any
number of physical pixels. So you know when you say 10 pixels, it might not be 10 pixels
at all. It could be whatever the algorithm is trying to work out, you know, how big to
draw it. But CSS pixels do help us make things roughly look the same size on different screens.
So you know if something's roughly arms length away, it should all look the same size regardless
of how many physical pixels there is on the screen, which is helpful but it means this
whole term of pixel perfect becomes a little bit tricky. And this is why pixel perfect
design is hard is because pixels are not perfect. Like one physical pixel is not one digital
pixel, one digital pixel is not one CSS pixel, and one CSS pixel is not the same on every
screen. So it becomes really difficult when you're trying to explain to a designer why
you know they're 10 pixels isn't 10 pixels. And so moving on to the problem with pixels.
As I've just said, you know like you can draw something out to be 10 pixels on a screen,
it might not necessarily be 10 physical pixels wide, but it will always be the same size
on a particular screen. So if you in your browser say I want this thing to be 10 pixels
wide, every single time the browser draws that it'll be the same physical length on
the screen. And static measurements by definition are not variable. So for example, if you are
instructed to drive a car at 60 miles an hour, you will always drive 60 miles an hour. It's
just a static unit of measurement. And the same with the 10 pixels variable, sorry, the
10 pixels measurement. But user preferences are not static. So in Chrome, for example,
the font size can be medium, which will be 16 pixels by default. But then you can go
into the browser settings and you can change that. So you can have very small text, which
will be 10 pixels. You can have small text, which will be 13. You can have large, which
will be 20. Or you can have very large, which will be 24. If you're like my dad and you
need everything to just be massive all of the time, you'll go straight in them settings,
bag it on 24, and then you'll probably find nothing changes. And this is where static
measurements can actually cause some accessibility issues. So things like font sizes and margins
and patterns, which are set using pixels, will never actually react to the user's browser
settings. So this is an example of Facebook, which does set everything in pixels. And basically,
if you go into your browser settings and you change small or medium or very large, like
nothing happens. I think in the dev tools, you can see the font size change slightly,
but that's the only thing that changes. Now, using pixels as a static size is not actually
a WCAG failure on its own. The web content accessibility guidelines, they care if you
can zoom in at 200% and then everything doesn't break. But they don't necessarily care whether
the content responds to the browser settings. But in situations like my dad, for example,
where he has the font size on very large, if he's on his phone and he goes on a website,
the font size always just -- if it's set in pixels, it's just always the bare minimum.
Then he has to start trying to zoom in on his phone, and then he ends up starting to
scroll around in two dimensions and everything's just kind of off. Whereas if it just responded
to the browser settings, he'd just be able to scroll up and down and everything would
work. So it's not a technical accessibility failure, but in real life situations, I've
definitely seen it where it affects people trying to kind of get around this. And also,
it means that when you're zooming in on the browser, if you're using manual zoom, like
my view shown earlier, it's not a great experience. Like, this puts an additional burden on the
user. So every time they go to a website, because it doesn't persist across domains,
so every time you go to a website, you can zoom in at 200% and you can navigate around
that website. But then as soon as you go to a different one, you've got to zoom in at
200% again, so the whole thing becomes really tedious.
The other thing that is a problem is that it just makes everything bigger. Like, when
you zoom in on the browser, like borders, on inputs, like everything just gets bigger.
If you zoom in far enough, you can be filling in a form and you've got like a 30 pixel border
on you and everything just looks a bit trash, really. So using relative measurements creates
a more accessible experience. And relative measurements use a reference point. So now
if we talk about the car example, if you're told to drive 1.2 times the speed limit, I
realize now this is terrible advice. Don't do that. Drive at the speed limit. It should
have been like 0.5 of the speed limit. I realize now, yeah, don't do this. But yeah, if you
drove a car 1.2 times the speed limit, if you were on a 50 mile an hour limit, you'd
drive 60 miles an hour. If you were in a 60 mile an hour limit, you would drive 72 mile
an hour. So common relative units we can use in the browser are percent, ems, rems. But
percent and ems can be challenging. So when I've tried to explain these concepts again,
normally to designers or people who don't necessarily know the ins and outs of browsers
and things, their reference points change, which, depending on which CSS properties they're
used on, means that you can essentially end up with different sizes. So for example, 1M
is not 1M. If you set your font size to 1M, the font size will use the parents element
font size to then set itself. But if you use it on a margin, it'll use the font size of
itself to set the margin. So you end up with these sort of variations in what size you
might actually get in your design. And ems and percent also suffer from a problem called
compounding, where because they are using their parent elements, when you nest them
under themself, you can end up with exponential results. So if you, for example, had a child
that was supposed to be 2M and the parent was 16 pixels, you'd want the font to be 32
pixels. But if you nest a child within a child, the first child becomes the parent. So now
it's doing 2M of 32 pixels, which would be 64 pixels. And if you nested it again, you'd
end up with 100 and I can't do math, 28 pixels. I don't know. So yeah, this compounding problem
can be challenging. So then we've got rems or root ems, which is the font size of the
root element, the HTML tag, if you like, and that inherits from the browser settings. So
this time, if we use rems, then we can get a nice, we can get access to those user preferences
and we can use this to our advantage. So a rem is whatever the user chooses in the settings.
So we said before that could be 16 pixels at medium, it could be very large at 24, it
could be very small at 10. And one rem does equal one rem. So if you set the font size
in the browser to be 16 pixels, and then you use it on font size or margin, then it will
emulate whatever it's set in the browser. So everything will be as you kind of expect
it to be. So rems don't compound either, the same way that ems and percent do. So we can
nest them as deep as we want and it will always kind of work out the way that we expected
it to. So this is an example where, you know, things of margins and font sizes and things
have been set up using rems. And now when we change the settings in the browser, you'll
see that everything just kind of responds to those things. So you don't have to actually
zoom in on the website anymore. You come to this website and your font size is set to
very large, it will just respect it off the bat and you don't have to then zoom in and
do all of that stuff. And rems are great, but we still need a system. So we can replace
pixels with rems and things will scale, but we still shouldn't just be sitting squinting
at Figma and like eyeballing values and just going, "I think that's about two rems." Like,
we still need a system in place. So I'm going to talk a little bit about harmonic scale.
And this is about to get a little bit weird, but it is design related, I promise. And people
might have heard of harmonic scale or modular scale. There's a really good book called Every
Layout by Hayden Picker and Andy Bell, where they talk about this in more depth and they
give a lot of, it's a really good book. If you have not read it, I imagine everyone probably
has to be honest in this room, but yeah, if you haven't, it's definitely worth looking
at. So when we talk about harmony, if we look at the Oxford dictionary, it says it's the
combination of simultaneously sounding music notes to produce a pleasing effect. So good
music is not random, like harmonies only exist because of the physics of sound waves. So
if you put waves together where the high and low points meet up, they will create harmony.
And humans can sense harmony. Like even if you don't understand musical theory, you just
know when a note is off. It just feels wrong. So we have these things called harmonic scales,
which is a defined set of notes that mathematically complement each other to create harmonies.
So if you're learning to play a guitar or whatever and you learn your scales, then you
know you can play, if you've got to knock a solo out, then you can just play any of
them notes and they should just work together, in theory. So for example, some notes in the
C major scale are C, G, C, E and G. And hopefully the sound will come out, but you can play
any of the notes in the scale and they'll work because science.
So you can play them in order, you can play them all together, but mathematically, because
those waveforms line up, they just sound quite nice. If a single note is not part of the
scale, hopefully you'll realize that it just feels not, it's a bit, makes you feel a bit
uneasy.
So yeah, without harmonic scales, making good music would be a lot of trial and error. I
mean, you'd literally just be sitting there going, nope, that feels wrong, that feels
wrong, that feels wrong. And we can apply the same logic to visual design. So if we
design using a harmonic scale, or it's also known as a modular scale, we start with a
base size or a fundamental and then we use a ratio to calculate the harmonic sizes off
the back of it.
And choosing, when you're looking to choose a base size or a ratio, it can depend on the
kind of style you're looking for. If you've got quite a, like a plain website, you might
have a bigger fundamental or you might have a bigger ratio. If you've got a really content
dense one, you might want to choose something smaller, but ultimately it doesn't really
matter what fundamental or what ratio you choose, but it is normally better to pick
one that's based on a little bit of logic. So 16 pixels can be a good fundamental because
that's the default font size in the browser. And 1.5 can be a good ratio because that's
the minimum line height that's used to assess text space in WCAG 2.2. So that could
just be two reasons why you picked those, but you could pick anything that you wanted.
Then we multiply and divide each increment to create the scale. So if we start with 16,
we would do 16 times 1.5 because that's our ratio, we'd end up with 24 pixels. So the
next size up would be 24. Then we would take 24 and we would multiply that by 1.5 again
and we would get 36. And if we went the other way, we'd take 16 divided by 1.5 and we'd
end up with 10.67 and so on and so forth. So we'd end up with this harmonic scale for
design where essentially our waveforms would line up based on the sizes that we used. And
the scale is not linear, so choosing sizes becomes easier as a designer. Like if it looks
too big, then we just use the next size down and we don't have to sit and eyeball things
anymore. And the whole idea of it being not linear means that you don't end up just with
increments of like 10 pixels, which is what I assume some designers would try and do just
to maintain some semblance of control. And I think this is a good point to make is that
you know your scale should only need two or three sizes in each direction most of the
time. If you end up with too many options, then you're probably trying to cling to too
much control and you just need to relinquish it. So in Figma, we can use variables to create
a harmonic scale in pixels. So you can actually go into Figma, you can set up a whole bunch
of number variables. So the only annoying thing about Figma is you can't calculate off
another variable.
That's the only thing annoying about Figma.
Sorry, the only annoying thing in this context about Figma. Yeah, God, that would be an entire
talk in itself that we wouldn't get through in 30 minutes. But yeah, in Figma you can
do this and you can do math in the input when you are setting your variables, but you can't
use other variables to calculate off, which is annoying. I'd rather just be able to set
a variable like scale zero and then do 1.5 times scale zero, but you can't do that in
Figma. But you can set them up and then once they're set up once, you can then just use
them in all of your margins and your font sizes and all that sort of stuff. And in CSS,
you obviously can use variables. So we can create our harmonic scale in REM. So we can
just use the calculate function and we can pass in the variables from previously. So
we can literally just set the ratio and the kind of base scale at the top and then everything
else is just done automatically.
And if designers and developers are using the same scale, everything ends up automatically
in sync. So the designers are in Figma, they're using variable scale one and the developer
has variable scale one and then nobody has to really worry about eyeballing those pixels
and screenshotting the browser and overlaying it in Figma and whatnot. We just trust the
system.
So a wrap up. Like pixel perfect is an outdated way of thinking about design. Like in 2025,
we shouldn't be squinting at Figma and just trying to work out if the pattern looks better
at 10 or 12 pixels. Like we should just trust the system. I mean, the amount of times where
you know, I've literally been in conversations where two designers are arguing over two pixels
and that just, I cannot grasp why that is a thing in 2025. There's obviously better
ways to solve this problem.
But designing in systems is better for everybody. Like designers spend less time visually balancing
designs and developers spend less time writing custom CSS and overriding all of the stuff
that's kind of already in the system. And I think as Jerry alluded to earlier, there's
a lot of time that gets wasted prepping for dev where a designer's job is literally to
go through that Figma file and eyeball all of the margins and everything so that the
handover is as smooth as possible. And I mean, you know, it takes up to a day sometimes to
go through all, you know, how inefficient can you get really.
And scale, scale. If everyone just started using bigger screens tomorrow, you can just
go in and adjust your ratio and your base size and then everything will just work if
it's set up properly. Everything will just scale. Even if the spacing changes, the balance
will remain because the scale has been set up to work mathematically.
Pixel sizing is still useful for some things though. And these are things which shouldn't
scale. So if you are putting a border on something and you want it to be three pixels, that's
perfectly acceptable. That means that when somebody comes in with their 24 pixel very
large size, the border still stays the same. Whereas obviously if you'd set that in rems
or whatever, it would scale with it. So pixels in some absolute positioning, like if you
want something to be at the top right of the screen, for example, and it's like 50 pixels
down, you don't want to necessarily be using a scalable size there because then when people
come in, it'll push everything over. So there is still some uses for pixels, but it should
only be things where everything, you want it to remain static.
And I guess if you take nothing away from this talk, take this away and that's that
nobody needs an app or a website to be pixel perfect, but everyone needs it to be usable.
And that's everything. Thanks.