The issue #
I think there is often a little bit of misunderstanding when frontend developers and designers talk to each other about dimensions on the web.
Designers generally design in pixels, obviously. Frontend developers then usually develop in ems and rems.
This post wants to bridge a knowledge gap that I feel might exist.
(I know other units also exists, but I think the ones covered in this article are the most important for a good designer-developer communication)
A simple technical explanation #
A pixel is the tiny dot that makes images on the monitor.
If you specify that an element has to be 20px wide, it will be 20px wide.
It will not be affected by what is around it or by its own font-size. If a user will change his/her accessibility settings, a pixel remains unaffected.
With rem units, one unit is relative to the font-size of the root html element.
It will not be affected by what is around it nor by its own font-size. In this regard it's similar to a pixel value. However, when a user will change his/her accessibility settings, rem units will be affected.
With em units, the unit is related to the font size of the element itself.
Em units will be affected by accessibility settings.
** If we have a box with font-size: 16px, and the width is 10em, it will be rendered on screen with a 160px width. If we apply a 2em padding, this padding will be 16 * 2 = 32px.
This is very useful because we don't need to explicitly define spacing of an element in pixels.
We can simply say that the padding equals 1em, and it will mean that the padding equals the font size, whatever it is. So basically we are specifying ratios relative to the font size, instead of absolute values.
When to use Pixels, Rems and Ems
My general rule of thumb as a developer is:
- Use pixels for elements that need to be rendered always at the same size. I probably only use this for borders.
- Use Rems for font-sizes, and for spacing elements between each other
- Use Ems for spacing, padding, margin, width and height.
In my experience, Ems should be avoided for setting font sizes, because they easily becomes complex to manage when we have many nested components. Rems for font-sizes are much easier to reason with.
Ems are perfect for setting spacing and sizes because this unit grows with the element's font-size.
In general, in frontend we should almost never use pixels to avoid all sorts of issues.
The advantage of this approach
By using the approach above, we can:
- Create a layout that harmonically grows/shrinks when a user changes the accessibility settings of his browser.
Elements created with the pixel unit will not grow/shrink.
- Forget about setting exact numbers for padding and margins on each element. Instead of setting a padding to 16px, we could set it to 1em, knowing that it will grow/shrink automatically depending on the font-size of the element.
Example: If we drop the element inside a box with a font-size of 32px, the padding will be 32px. If we drop the element in a box with font-size of 50px, the padding will be 50px.
- We can easily manage fonts, because rems are easy to reason about once we know the base font size of a website. I generally set the base font to 10px so that 1.6rem is 16px, and 4rem is 40px. Easy.
The web is not a printer
In my opinion designers (and stakeholders) need to take into consideration the fact that items should be allowed to grow or shrink as the font sizes change. They need to understand that elements can be subject to custom accessibility settings and accept the fact that, as someone said before me, "the web is not a printer". Their designs in Sketch are guidelines, not the single source of truth; the source of truth is still the CSS written by the developer, like it or not.
What should designers do
Designers should design nice and balanced UIs without worrying too much about exact pixel sizes and pixel spacings; they should just communicate to frontend developers what are the ratios they have used for their elements, and these will be replicated using rem for font sizes and em for paddings and margins.
Example: when they design a button, they could tell the frontend developer that the padding should be 1 unit, and the margin on the left is equal to 0.5 units (where a unit is equal to the font size).
I believe that if this concept is understood, communication between developers and designers would be much simpler.