Magic Numbers in CSS

Nick Gard
3 min readJul 29, 2019
Photo by Volkan Olmez on Unsplash

One of my more common critiques on code reviews of CSS changes is the presence of magic numbers. I’ll see a property being added with a nonsensical measurement, like top: 13px, and I’ll ask to contributor why it exists. More often than not, the answer is, “because it works.” The problem with this answer is that it only works for you, now. For another user on a different device in the future, it probably won’t work. Let me explain…

What is a magic number?

First, let’s clarify what exactly a magic number is. A magic number is a measurement without context. It is a number whose reason for existence is not self-evident or clear. It’s presence in a CSS property value will cause you to wonder where it came from and why it’s that number and not some other number.

Why are magic numbers bad?

There are two reasons not to use nonsensical numbers in CSS. First, any measurement that is not clear or self-evident risks being separated from its reason for existence. Once separated, it will suffer one of two fates: (1) it will live forever, as every developer is afraid to change it, not knowing what it will break, or (2) it will be changed independently of whatever it was supposed to correspond with, breaking some styling.

Consider this example:

.box { padding: 10px; }/* 32 lines of CSS */.first { margin-top: -10px; }

If the box class ever changes, the first class should also change since its property “undoes” the box rule. These two numbers are linked, though that link is not clearly expressed here. It’s also unknown from this code if 10px is a standard measurement for the app.

The other reason not to use magic numbers is that they often come from measuring an instance. A developer knows that the body needs to be moved down to allow for the fixed-position header, so they open up the web inspector, measures the height of the header, and adds that magic number as the top padding of the body. Unfortunately, the header’s height may grow or shrink based on the browser’s or screen’s dimensions or based on the changing content of the header. That measurement is stale almost as soon as it is taken.

Writing bespoke numbers in CSS is usually the wrong solution to whatever problem you’re attempting to solve. The web is fluid. Screen dimensions, font sizes, and content all change. You need to author CSS that can change with it. That is why absolute units (px, pt, cm, in, q, mm, pc) and magic numbers should never be used.

Recommendations

For me, the following measurements are always self-evident: 0, 1px, 1em, 25/50/100%/vw/vh. These correspond to “nothing,” “hairline border” (that’s exclusively what I use 1px for), “as tall as the text” (1em isn’t exactly the height of the text, but it’s a close generalization), a quarter/half/whole of itself, its parent (%) or the viewport (vw/vh). You would be surprised how much can be accomplished with just these. Start with these values.

Other measurements that are used should be clear from their context, like .spacing-medium { margin: 1.614em; }. Numbers like these should not one-off and should be held in a SCSS or CSS variable.

An exception to this “No Magic Numbers” rule is media queries. Media queries should always be written in em units, and should be authored for the specific case it’s used for. Having preset media query values stored in a variable is unnecessary because it is not often that two sections “break” at the same measurement. (If it’s not obvious from this statement, I consider layout breakpoints like “mobile” and “desktop” to be an anti-pattern in design and in CSS.)

--

--