margins and ems

January 25, 2011

There's more to understanding css than just getting to know the rules or assigning values to a list of properties. The css language was constructed based on a rule set, a series of paradigms that define the way the language is supposed to behave. Once again (remember css proximity) we're going to try and find out how and where the programmer's mind is clashing with the human mind, causing confusion and mishaps in cssland.

the problem

The issue at hand is one that popped up on this blog before (check the heading headaches article). Rather than try and find solutions within the current context of css, let's do one better and let's go looking for the reasons behind the trouble some of us have been experiencing when margins clash with em-designs.

The main issue here is that margins (set in ems) on a box are influenced by the font-size defined on that same box. This becomes very annoying when you're playing around with headings and the left and rights margins of the heading box keep changing every time you adapt the font-size of this heading. What you (usually) want is to create a nice vertical grid, but when you need to pull out your calculator to recalculate the correct margin values time after time it becomes tiresome really fast, not even talking about browser-specific pixel value roundings.

Even though the issue itself is slowly dying (because most people stopped making em-designs), I believe the inner workings of the problem are still very much worth checking out.

the box model

The main culprit causing us all this trouble is the css box model. The box model describes the spatial properties that define a css box, including widths, heights, borders, paddings and last but not least, margins. If you see it explained it looks perfectly sane, seemingly providing us with a good model for defining the dimensions of a box and its position based on its context.

To make things as easy as possible, all em-values on the box will be calculated based on the font-size defined on that same box. So if I choose to increase the font-size, widths, paddings and margins will change accordingly. It's an easy rule to remember, but one that does not necessarily match our own mental model of how a box should behave.

real life boxes

So where does the css box model differ from real life boxes then? The answer is simple: a real life box is defined by its borders (sides, walls, whatever). For example, we consider a cardboard box the box itself and everything that is contained within the box. As far as boxes are concerned, you're either outside or inside and everything that's outside the box is not part of you, nor do you care what happens with it. Outside is simply not your responsibility.

The concept of margins doesn't really exist in the simple life of boxes (we do have similar concepts though, like "personal space"). The space outside of the box is part of its context and should be monitored by that same context. If we translate this back to css, this would mean that margins should not be defined by the font-size set on a box itself, but by the font-size set on its context.

Considering the fact that font-sizes are inherited values, this should pose little practical problems to implement. It also fixes our problem with the change in computed margin values. On the other hand, it does complicate the rule set of the css box model, where a small exception should be made for calculating margin values defined in ems.


Not that I'm expecting the powers that be to change the css box model, I'm sure there are way too many practical problems (breaking existing implementations) that would stop this from ever happening, but it would've been nice if they'd thought of this a little earlier. It's once again a good example of programmer logic interfering with simple human logic, resulting in easy rule sets but leading to sub-ideal practical implementations.

We could of course add yet another css property to control the behavior of the css box model (just like they did when they introduced the box-sizing property - maybe something like box-calculate), but I'm not sure if that's really worth the trouble. Sure I would be quite happy with it, but I'm not really confident many others are waiting for such a property.

Like I said at the start of this article, not many people are faced with this problem anymore as ems units are getting out of fashion, but that doesn't change the fact that the problem still exists within the core of the css box model. Just something to think about.