margins & paddings pt5

After my first two attempts I haven't made any real progress yet, and I have only one attempt left to find a good, solid solution. Time to get serious and see how we can fix the issues we've been having with our previous attempts. Time for a change of tactics. Here comes the third and final solution to our margins and paddings problem.

example code & test cases

padding vs margin test cases <div class="parent"> <div>...</div> <p>...</p> <ul>...</ul> </div>

In case you forgot, here's a quick reminder of the setup we're using. Three test cases and a very simple piece of markup code to build our test cases. Nothing new here, so let's continue as quickly as possible.

the final solution: throw out the padding

One issue that's been bothering me in the first two solutions is the fact that we have to override the padding on the parent each time we want one of our children closer to the parent than the parent's padding dictates (test case 2). There's really only one way around this, which is to lose the padding on the parent altogether. To compensate for the padding, we put full margins on all children. At first sight, it looks like we might lose some flexibility by doing this but let's see where this solution gets us.

case 1

1/ .parent {overflow:hidden;} 2/ .parent>* {margin:1em;} -/ /* ------------IE6 fix ------------ */ 2.-/ .parent p, .parent li, .parent div {margin:1em;}

As you can see, we've lost the padding on the parent and added a single margin declaration for all children. This creates an equal distance between all children and their parent. And all of that in only one declaration. Seems we're on to something now.

The problem of the clipped background is still there, sadly. We faced this problem in our second attempt and it remains a nagging issue. And of course IE6 is still messing things up, but at least we've simplified the IE6 exception rules, so that's another tiny victory. As IE6 is lacking the child selector, there's really no good way for it to handle paddings and margins, this is as close as we're gonna get.

On the upside, we're not mixing paddings and margins anymore to create a single spacing effect, and the css really cleaned up too as we can set a base value in one simple rule with one single declaration.

case 2

1/ .parent {overflow:hidden;} 2/ .parent>* {margin:1em;} 2/ .parent>*:first-child {margin:0;} -/ /* ------------IE6 fix ------------ */ 2.-/ .parent p, .parent li {margin:1em;} 3.-/ .parent div {margin:0;}

Look at that, no more overriding previous padding declarations. Whatever margin we set as default, by simply resetting our margin declaration we reach the desired result. We can change the default margins all we want, this has no effect on the value of the reset. Pretty easy and quite flexible indeed.

case 3

1/ .parent {overflow:hidden;} 2/ .parent>* {margin:1em;} 3.1/ .parent>p {margin-top:2em; margin-bottom:2em;} 3.2/ .parent>p {margin:2em 1em;} -/ /* ------------IE6 fix ------------ */ 2.-/ .parent li, .parent div {margin:1em;} 3.-/ .parent p {margin-top:2em; margin-bottom:2em;}

The third example is still easy to accomplish but it does reveal one final hick-up. Either we restate the left and right margin (3.2) or we define the top and bottom margin separately (3.1). Solution 3.1 is definitely preferable as it doesn't restate any previous declaration, so adapting the css is much easier this way.

Nothing too serious but it would've been nicer if we could've avoided this last issue.

The verdict

This third and final solution is obviously the best one of the bunch. It doesn't mix paddings and margins to get the desired result, there's only a small dependency between the css declarations and it offers quite a lot of flexibility. If we check our guidelines again, this is without a doubt the solution that answers to most of our initial requests.


Maybe a little ironic, but I hope this series of articles proved that the commonly heard statement of paddings and margins in relationship to backgrounds and borders is really an exceptional case of using paddings and margins. When none of these visuals needs apply, work with margins, declared on the children from the parent. It gives you maximum flexibility, makes for easier fixes in IE6 and is just as flexible when it comes to transporting code blocks from one context to another.

The only real issue with this solution is the clipped background. Sadly there's no one good fix to this problem, but there's always a way out, so in the end it's not really a blocking issue. I hope this series proved helpful in trying to understand the finer points of paddings and margins. The series might rely heavily on several advanced css ideals and techniques, but the result is pretty simple. If you're wondering whether you should use a padding or margin without having to worry about any visual dependencies, use this rule:

.parent>* {margin:1em;}

I've been using it myself for a while now and it's made my css quite a bit cleaner and easier to manage.