61

Often times I see questions on the Hot Network Questions list like this that basically ask "how do I draw this arbitrary shape in CSS". Invariably the answer is a couple of blocks of CSS or SVG data with a bunch of seemingly random hard-coded values that form the requested shape.

When I look at this, I think 'Yuck! What an ugly block of code. I hope I never see this type of stuff in my project'. However, I see these types of Q&As quite frequently and with a high number of upvotes, so clearly the community doesn't think they are bad.

But why is this acceptable? Coming from my back-end experience this makes no sense to me. So why is it OK for CSS/SVG?

5 Answers5

117

Firstly, magic values are avoided in programming by using variables or constants. CSS does not support variables, so even if magic values were frowned on, you don't have much of a choice (except using a preprocessor as SASS, but you wouldn't do that for a single snippet).

Secondly, values might not be as magic in a domain specific language like CSS. In programming, a magic number is a number where the meaning or intent is not obvious. If a line says:

x += 23;

You will ask "why 23"? What is the reasoning? A variable could clarify the intent:

x += defaultHttpTimeoutSeconds;

This is because a lone number could mean absolutely anything in general purpose code. But consider CSS:

background-color: #ffffff;
font-size: 16px;

The height and color are not magic, because the meaning is perfectly clear from the context. And the reason for choosing the spefic value is simple because the designers thought it would look good. Introducing a variable would not help anything, since you would just name it something like "defaultBackgroundColor" and "defaultFontSize" anyway.

JacquesB
  • 61,955
  • 21
  • 135
  • 189
78

It's acceptable because these formats are not code, but data. If you were to remove all the "magic numbers," you would essentially duplicate every label, and end up with ridiculous looking files like:

mainkite_width = 200px
...
.mainkite {
  width: mainkite_width;
  ...

Every time you needed to change some data, you would need to look in two places. Granted, there are situations where it's nice to avoid duplication, like if you have a color that is repeated frequently and you may want to change in order to change themes. There are preprocessors and proposed extensions to address those situations, but in general, it's desirable to have numbers together with the structure in a data format.

Karl Bielefeldt
  • 148,830
25

The prohibition on magic numbers is the primordial version of this design principle:

Make decisions in one place.

But these are not magic numbers. At least, not as far as any coding style guide I know of is concerned.

width: 200px;
height: 200px;

They are clearly labeled. Sure, the numbers happen to be the same. But the width is the width and the height is the height. They are designed to vary independently.

Now if you have 5 objects that all had to have the same width and each independently hardcoded their width I would beat you with the indirection stick.

I wouldn't call them magic numbers if they are labeled, but I'd still beat you with the indirection stick.

candied_orange
  • 119,268
10

Because CSS is not a programming language, instead, it is the configuration file that contains the variable data for your program.

Currently CSS is so powerful that you can actually program in it, but that is besides the point. In essence it's still a stylesheet language.

Let's take a step back. Imagine we have a programming language that can draw on a screen. Imagine we want to program it to paint a web page.

At first we would enter tons of magic numbers in our code. The margin width, the text height, indentations, etc., etc.

jump(100) // The margin
drawTable(500, 500)
writeText("Hello World", 12)

So we extract the magic numbers, and put them on top of our file.

int margin = 100
int table = 500
int text_size = 12
jump(margin) // The margin
drawTable(table, table)
writeText("Hello World", text_size)

Now this is a bit ugly. We rather read our variable numbers from a configuration file.

margin 100
table 500
text size 12

Mm, that's a bit unclear... What do those numbers mean? What do those names mean? Let's formalize it a bit.

margin_left 10em
table_width 500px
table_height 500px
font_size 12px

But you know, we want to expand our program a little bit. We also want it to draw pages with multiple tables, pages without tables, pages with paragraphs or buttons and what more. Let's add selectors to our configuration file so we can specify what paragraph should have a larger font, or different text colour, perhaps we can support nested elements, perhaps we can use a general property in our configuration file, and then override it with a specific one in a few nested elements.


You feel where this is going, eventually you arrive as CSS. (And a browser to render it.)

Should we then add capabilities to our configuration file so we can avoid magic numbers again? Add variables? Add a configuration file for our CSS file? It feels a bit pointless if you remember our CSS file is that very same configuration file already.

But that is not true of course; your CSS file grows larger and larger, and eventually you run into the same problems as with the original magic numbers, the same number repeated all over the place, sometimes with a small transformations, etc.

Modern CSS however, allows many ways to avoid this repetition. You can use classes that apply to many elements, you can set style for all divs, but then override one specifically, and CSS 3 even allows some kind of variable usage.

That does not mean you need to start using CSS variable in every possible location. Use it where it makes sense and use it where you avoid duplication or where other techniques also available fall short.

In the end, you do not want too many magic numbers in your configuration file either :-)

Dorus
  • 459
5

Why is it [a bunch of seemingly random hard-coded values] OK for CSS/SVG?

It isn't OK. It's possible to write and maintain plain ".css" files, but eventually random hard-coded values will become a prevalent burden.

For anything other than extremely simple webpages, you will either have to develop a disciplined "find and replace" strategy, or use a CSS preprocessor with variables, or define styles via JavaScript.