Calculating Percentage Margins in CSS
Most web designers think they know CSS pretty well. After all, there isn’t that much to it — a few selector types, a few dozen properties, and some cascading rules that you barely need to remember since they boil down to common sense. But when you get down to the nitty-gritty level, there are plenty of obscure details that few designers truly understand.
When I examined the results of a free CSS test I’ve offered online for the past six months, I discovered one question that almost no one got right. Of the thousands of people who took the test, fewer than 14% got it right.
CSS Could Be The Hardest Language of All (5 Reasons Why)
A website may be built upon several web languages such as HTML, CSS, JavaScript, and PHP. Among these... Read more
The question boils down to this: How Do You Calculate Percentage Margins?
The Question
Say your site has a container div
, and inside that, a content div
:
Now, let’s give that content div
a top margin:
.content { margin-top: 10%; }
Okay, so it’s 10% … but 10% of what? That’s the question that only 13.8% of people can answer correctly. And keep in mind: these people have access to Google!
What I love about this question is that it seems like the answer should be obvious. So much so, that I suspect most people just take a guess (and guess wrong). But maybe it doesn’t seem obvious to you. I mean, if you really use your imagination, there are many ways the browser could conceivably calculate a margin like this.
So how about if I narrow it down for you since the question in the test is actually multiple choice. Here are your options:
- 10% of the content div’s height
- 10% of the container div’s height
- 10% of the content div’s width
- 10% of the container div’s width
Remember, only 13.8% of people can pick the right answer from this list. That’s way worse than chance!
Look closely at the answers; you’ll see there are really only two things you need to know:
Container or Content?
First, is the size of the margin based on the size of the content div itself, or on the size of the container div?
Now this isn’t a gimme, but you can probably trust your instincts. If I set a div to be 50% of the width of its container, and then I want its left and right margins to fill the rest of the space, I’d naturally set them to 25% each (so the percentages add up to 100%). For that to work, percentage margins must be based on the dimensions of the container.
Sure enough, two thirds of people who take the test get this part of the answer right.
Width or Height?
Second, is margin-top’s size based on the width or the height of that element?
If you’ve been paying attention, you’re probably on your guard already. For so few people to pick the right answer, this has got to be a trick question, right?
And yet, I bet you can barely believe that the answer isn’t height. Well, it isn’t.
Yes, we’re talking about a top margin here. Yes, the size of that margin is a vertical measurement. Yes, if a block is 50% of the height of its container, and you gave it a top margin of 25%, you’d expect that to be 25% of the height of the container. And you’d be wrong.
Don’t feel bad if you thought it had to be height. Nearly 80% of people who take the test agree with you:
It Makes Sense… No, Really!
Still don’t believe it? Here’s a quote from the W3C CSS spec:
The percentage is calculated with respect to the width of the generated box’s containing block. Note that this is true for margin-top and margin-bottom as well.
The same goes for top and bottom padding, in case you were wondering. As for borders, it’s illegal to specify their width as a percentage.
So at this point, you’re probably thinking the creators of CSS are either bonkers, or they just made a really dumb mistake. But I’m here to tell you, there are two good reasons to base vertical margins on the width of the containing block:
Horizontal and Vertical Consistency
There is, of course, a shorthand property that lets you specify the margin for all four sides of a block:
margin: 10%;
This expands to:
margin-top: 10%; margin-right: 10%; margin-bottom: 10%; margin-left: 10%;
Now, if you wrote either of the above, you’d probably expect the margins on all four sides of the block to be of equal size, wouldn’t you? But if margin-left and margin-right were based on the width of the container, and margin-top and margin-bottom were based on its height, then they’d usually be different!
Avoiding Circular Dependency
CSS lays out content in blocks stacked vertically down the page, so the width of a block is usually dictated entirely by the width of its parent. In other words, you can calculate the width of a block without worrying about what’s inside that block.
The height of a block is a different matter. Usually, the height depends on the combined height of its contents. Change the height of the content, and you change the height of the block. See the problem?
To get the height of the content, you need to know the top and bottom margins that are applied to it. And if those margins depend on the height of the parent block, you’re in trouble, because you can’t calculate one without knowing the other!
Basing vertical margins on the width of the container breaks that circular dependency, and makes it possible to lay out the page.
More on Hongkiat:
- Web Design: Equal Column Height With CSS
- 6 CSS Tricks to Align Content Vertically
- A Look Into CSS Units: Pixels, EM, and Percentage
- A Look Into: CSS3 Box-sizing