62

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?

14
  • 38
    What is a drawing, if not a random bunch of magic numbers (think of strokes between 2 (x,y) points, or arrays of pixels, etc.) that happen to look nice?
    – user44761
    Apr 7, 2016 at 15:02
  • 68
    Does CSS have variables? Does SVG?
    – Oded
    Apr 7, 2016 at 15:03
  • 36
    This is why many larger projects have a CSS preprocessor like SASS or LESS that supports variables.
    – Ixrec
    Apr 7, 2016 at 15:10
  • 2
    @Oded For CSS, there is some 40% global support for variables (so, not recommended unless you want to tell all your Microsoft visitors that they're not welcome). Microsoft will probably follow the trend in Edge, and mobile devices will eventually catch up. SVG, on the other hand, has the concept of variables in some forlorn draft status document, but they'll probably never be implemented.
    – phyrfox
    Apr 7, 2016 at 19:08
  • 12
    Why? Because they aren't magic numbers. CSS holds data, unlike a program which holds instructions. Although CSS is arguably turing complete, it is not a programming language. Apr 7, 2016 at 23:12

5 Answers 5

118

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.

18
  • 16
    Some values are indeed just chosen because "they look good". But the example the OP linked contains the same value several times, but it's not clear if they represent the same thing or only have the same value by coincidence. Also it uses a value of 198px which is the difference of the size of something else (200px) and a 2px border. Apr 7, 2016 at 16:08
  • 1
    @CodesInChaos: Yes, there are some cases where variables or some kind of dependency expressions would be cool.
    – JacquesB
    Apr 7, 2016 at 16:32
  • 21
    Note that CSS does support variables
    – phihag
    Apr 7, 2016 at 18:56
  • 29
    @phihag In the specs, yes, but in the wild, not so much (I don't consider 40% global support at the time of this comment as "widely supported". However, you're right in saying that, in the future, we will have CSS variables. And I did learn something new today, so thanks for that.
    – phyrfox
    Apr 7, 2016 at 19:01
  • 2
    @JaredSmith It's fine for a relatively large scale webapp, however for common (perhaps static) pages including a huge polyfill is overkill. Apr 8, 2016 at 19:47
79

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.

3
  • 22
    +1 because :"It's acceptable because these formats are not code, but data."
    – Pieter B
    Apr 8, 2016 at 12:20
  • 1
    "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." - Probably better done with classes anyway: .main_color { color: .. }, and using that class is the method of deduplication
    – Izkata
    Apr 8, 2016 at 16:40
  • 1
    Code which determines the look and feel of an application is still code and not data.
    – ESR
    Nov 19, 2018 at 1:42
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.

6
  • 4
    If you had enough objects to need a variable, you have enough objects to create a new class.
    – ZomoXYZ
    Apr 8, 2016 at 3:44
  • 1
    This is the best answer, as it shows the point: Those are not magic numbers. Apr 8, 2016 at 5:27
  • 2
    " 5 objects that all had to have the same width and each independently hardcoded their width I would beat you with a stick." Welcome to the fun world of web design. Apr 8, 2016 at 5:51
  • 2
    Magic numbers are not only problematic because of "Make decisions in one place" (aka DRY), but also because they are hard to understand.
    – sleske
    Apr 8, 2016 at 11:08
  • Is there an alternative to being beat with a stick?
    – djechlin
    Apr 8, 2016 at 21:02
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 :-)

4
  • Why does it matter where the redundancy is? Isn't maintenance going to be a problem no matter where it is? Apr 9, 2016 at 19:56
  • @PeterMortensen This is always a consideration between low development time, or high maintainability. High redundancy is easy to develop because you can quickly change things here and there, low redundancy is easy on maintenance because you can quickly change global style. In practice you want to be somewhere in between the two, because face it, having a global style makes it a lot easier even to add new pages, but having every last obscure feature adhere any possible global style change takes forever to develop.
    – Dorus
    Apr 9, 2016 at 23:25
  • It's good CSS has features in both directions. And it is up to the web developer to decide how much time to spend on reducing redundancy and increasing maintainability, or time to spend at crunching out new pages/features. Interesting enough, the same holds true for any other programming language where you can spend months to lay out the perfect design, or days to whack down your program, and months to hunt down impossible bugs.
    – Dorus
    Apr 9, 2016 at 23:28
  • Interesting enough i just ran into this question that talks about taking abstraction too far, and losing out on both maintainability and development time.
    – Dorus
    Apr 10, 2016 at 0:22
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.

Not the answer you're looking for? Browse other questions tagged or ask your own question.