margins and ems/outside the box

published on:
January 25, 2011
comments

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.

conclusion

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.

Comments

JJ

comment number
date
January 25, 2011 14:46

Hmmm, the change you're proposing is deceptively simple.

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.

When you say the box's “context”, what do you mean? Its parent element? Its containing block? Its BFC? I can't help but think you mean the box's “visual context” because your analogy of the real physical box is very visual and intuitive: “if something is outside of a cardboard box, it appears outside of it.” But what if a box is rendered on top of some box that is not an ancestor element or its containing block? Visually, according to your analogy, its margins would “belong” to the boxes it's rendered on top of (because thats where the margins appear to be). To go even further, what if it overlaps with several boxes?

The problem is, boxes in CSS don't abide by the same rules as boxes in a 3 dimensional reality would. In reality, if a cardboard box had a containing block, presumably, this cardboard box would be physically inside of another cardboard box. CSS doesn't work the same way: Boxes in CSS can be painted in a completely different location, thus giving the box a completely different visual “context”. CSS can render boxes outside of the boxes they're technically contained in - something that is logically/spatially impossible in reality.

The analogy doesn't seem to be a good basis for this change, and if you meant something else by “context”, I don't see how the analogy is relevant.

Niels Matthijs

comment number
date
January 25, 2011 15:15

The danger with analogies is that people take them too far. With "context" I mean its immediate parent. This is fine for most situations.

You do make a good point for positioned elements, though I assume the change would lie with the left/right properties rather than margins, where the reference font-size could be that of the reference parent (pos:abs/pos:rel above).

Haven't run into problems with the second example though, but I don't see any immediate problems with the proposed change above. And I believe the main analogy still stands and illustrates where the box model differs from our own mental model.

JJ

comment number
date
January 25, 2011 15:28

Going by the box's parent element's font-size seems to be the worst choice to me. If anything I would've gone with its containing block, ...or its nearest ancestor that forms a block formatting context since it has a direct affect on how margins behave, but I would even find that slightly flawed.

I guess to put it simply, the way I view it: The reason this isn't a good idea is the same reason having boxes inherit their ancestors' margin properties would be a bad idea: they're not necessarily "spatially" relevant to each other.

In the end, I think it would make things more complicated. Em units would have to be redefined to include a special exception, or different behavior, for margins.

the_dees

comment number
date
January 25, 2011 18:17

There is a 'rem' unit in CSS 3 Units and Values. That may help.

Chaning something already established is impossible.

Felix Miata

comment number
date
January 27, 2011 02:57

Seems a deviation from the em sizing plan makes sense for margins. Margins usually are small values, usually leading to bothersome rounding issues. Why not use px for small values instead?

The other deviation option, not fully supported yet, but in CSS3, and so available long before any change in box model could take place, is the rem unit.

Bobby Jack

comment number
date
January 28, 2011 14:08

Broken link: "heading headaches"

Niels Matthijs

comment number
date
January 28, 2011 14:39

Thanks for noticing Bobby, link fixed!

Matthew

comment number
date
January 29, 2011 18:30

It's also ridiculously stupid that the width of a box is defined as the width of it's content, which has no real-world parallels and makes things like width: 100% annoyingly useless. The box model was a horrible idea from day one.

John

comment number
date
January 30, 2011 20:43

I really don't see what the confusion is here? I use ems on almost every site, I have a couple of very simple rules and it seems to work.

1) Only put font-size on the following elements (p,h's,li) 2) If stacked elements inherit reset the font size (li ul reset font-size to original size) 3) Set base font-size to 10 (no matter what the vertical rhythm is)

Also context should not dictate content. So .boxType h2 {}, should really be .boxtype {} h2.large {}

The other way to use ems, is originally do your margins or padding in px, then convert to ems when you're happy with the element.

* required fields

Leave your data
Leave a comment