In a design system, why do hairline dividers and centred icons sometimes look blurry on certain screens, and how do specs prevent it?
answer
- fractional scale factors
- half a hardware pixel
- anti-aliasing versus rounding
- odd difference when centring
- hairline as a platform primitive
basics
~20 sWhen a logical value maps to a fraction of a hardware pixel, such as a 1-unit line at 1.5x or an icon centred with a half-unit offset, the renderer blurs or rounds it. Specs prefer values that land on whole pixels.
solid answer
~40 sEverything is finally drawn on whole **hardware pixels**. At a scale factor of 1.5, a 1-unit divider is 1.5 pixels, so the renderer either **anti-aliases** it across two partly shaded rows, a soft grey smear, or **snaps** it to 1 or 2 pixels, making identical dividers look different thicknesses. Positions do the same: centring a 15-unit icon in a 24-unit button leaves a 4.5-unit offset, a half pixel at 1x. Specs prevent it by keeping thin, repeated edges on values that stay whole at common scale factors, keeping centring differences even, defining a **hairline** as the thinnest line the platform can draw rather than a fractional logical value, and testing on fractional-density screens, not only on 1x and 2x.
go deeper
Recall that logical units become hardware pixels by multiplication, and that fractional results get blurred or rounded.
Explain the two failure modes, anti-aliased blur and uneven rounding, and why centring an odd size in an even box creates half-pixel offsets.
Show how you would diagnose a blurry divider or icon on a 1.5x device and turn the fix into a system rule rather than a one-off nudge.
Weigh how strictly to enforce whole-pixel values against fluid and text-relative sizing, which produce fractions by design.
## Where half pixels come from Everything a design system specifies ends up drawn on whole **hardware pixels**. A logical value becomes hardware pixels by multiplying it by the device's **scale factor**. When the product is a whole number, the edge lands on a pixel boundary and looks crisp. When it is not, the renderer has to decide what to do with a fraction of a pixel. Fractions appear in three common ways: 1. **Fractional scale factors.** Many devices use factors such as 1.5, 1.75 or 2.75, so a 1-unit line becomes 1.5, 1.75 or 2.75 hardware pixels. 2. **Half-unit positions.** Centring a 15-unit icon in a 24-unit button leaves 4.5 units on each side; at a scale factor of 1 that is half a pixel. 3. **Computed sizes.** Space-relative and text-relative values, such as a third of a container or a size derived from a text size the user raised, routinely produce fractions. ## What the renderer does with a fraction | Strategy | What you see | Where it hurts | |---|---|---| | **Anti-aliasing**: shade the two pixels the edge straddles | a soft, greyish edge; a 1.5-pixel line looks like a faint two-pixel smear | hairline dividers, icon strokes, small status dots | | **Pixel snapping**: round the edge to a whole pixel | crisp edges, but identical values render at different sizes | repeated dividers, evenly spaced rows, icon alignment | Many rendering engines snap some things, such as box edges and text baselines, and anti-alias others, such as vector shapes and transformed layers, so one screen can show both symptoms. Snapping trades blur for **inconsistency**: three 1.5-pixel dividers in a list of appointments might render at 1, 2 and 1 pixels depending on where each falls, and the gaps between identical rows can differ by a pixel. It reads as sloppy even when nobody can say why. ## How specs avoid it - **Prefer values that stay whole at common scale factors.** Multiples of 2 are whole at 1x, 1.5x and 2x; odd values and halves are the usual offenders. - **Keep centring differences even.** Make icon and container sizes both even, or both odd, so the offset is a whole unit. - **Define the hairline as a platform primitive.** A hairline means the thinnest line the device can draw, one hardware pixel, not a fixed logical value. A 0.5-unit border is one hardware pixel only at 2x; at 1x it is blurred and at 3x it is 1.5 pixels. - **Keep icon geometry on whole units.** Strokes aligned to whole units land on pixel boundaries at 1x and 2x, while a 1-unit stroke centred on a grid line straddles two pixels at 1x. - **Export bitmaps per density** rather than letting the platform scale one bitmap by a fractional factor. ## Diagnosing a blurry element 1. Note the device's scale factor. Blur that appears only on 1.5x or 2.75x devices points at fractions. 2. Multiply the element's size and position by that factor; any non-integer result is a suspect. 3. Walk up the container chain. A parent sitting at a half-unit position shifts every child onto half pixels, however clean the child's own values are. 4. Fix the value in the component or the token, not with a one-off nudge on one screen, and add that device class to visual tests. ## Where to be pragmatic Whole-pixel discipline conflicts with fluid and text-relative sizing, which produce fractions by design. Most systems accept fractional sizes for large surfaces and for text, where a sub-pixel difference is invisible, and enforce whole values where edges are thin and repeated: dividers, borders, icon strokes and small indicators. In a veterinary clinic booking app, that means the appointment list's dividers and the small availability dot beside each slot are specified exactly, while the width of a slot chip in a fluid row is allowed to land wherever the layout puts it. The goal is not to eliminate every fraction; it is to keep fractions away from the thin, repeated edges where the eye notices them.
- If renderers snap to whole pixels anyway, why should a spec care?Snapping trades blur for inconsistency. Three dividers that are each 1.5 hardware pixels may round to 1, 2 and 1 depending on where they fall, and the spacing between identical rows can differ by a pixel, which makes a list look uneven. Choosing values that are already whole at common scale factors removes the rounding decision.
- Why does a 0.5-unit border fail as a universal hairline?It is one hardware pixel only at a scale factor of 2. At 1x it is half a pixel and gets anti-aliased into a faint blur; at 3x it is 1.5 pixels and blurs or rounds. A true hairline is defined as the thinnest line the device can draw, which each platform can supply directly.
saying these in an interview costs you the question
- High-density screens make half-unit values harmless on every device.
- A 0.5-unit border reliably draws a one-pixel hairline everywhere.
- Blurry icons are always the export's fault, never the layout's.
- Scale factors are always whole numbers, so fractions cannot occur.
- Renderer pixel snapping means specs never need to choose values carefully.