margins & paddings pt4

Last week we looked at a first solution concerning the margins and paddings problem. This try-out provided some good information on the problems we are facing when dealing with margins and paddings. Especially IE6 was acting up in it's failure to target first-child elements. So let's try to fix that this time around. Time to work on our second solution.

example code & test cases

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

The setup remains the same as before. We have a very basic code example which we'll use to build the three tests. On to the real work.

the second solution: 3/4 padding + top margin on all children

The second solution builds on the first solution and tries to fix the main issue we had the first time around. The problem was that we lacked a good way to single out the first element in IE6 to nullify it's top margin. We'll try to fix this by making sure there's no top padding on the parent element, making the need to find the first element obsolete.

case 1

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

The css above should do the trick. You'll notice that we've reset the top padding on the parent element to zero, then we've applied a top margin to all direct children. The plus of this technique is that it makes the css a lot easier to comprehend, and IE 6 proves less of a problem, although all children still have to be defined separately.

The IE6 fix is a little more consistent although the lack of a decent child selector remains a drag. The only real issue with this solution is that we've used margins and paddings to create one single effect (namely the space between the parent and its children). This is annoying when you want to change the whitespace, especially when the spacing between the children should be different from the spacing between the children and their parent.

But there's a nastier problem ahead. When the parent container lacks any declaration to prevent collapsing margins, you'll see that the top margin on the first child will take effect but will clip the background of the parent element. How 'bout that. We can fix this by adding a border to the parent element, but that's a horrible hack. Adding the overflow property also works but mind that this can have unwanted effects when elements are positioned outside of the parent container. Other options are floating the parent or establishing a new block-formatting context, but none of these options are foolproof. And the strangest thing of all ... IE6 hasn't got this problem.

case 2

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

The second case is again quite easy, we simply single out the first child and apply a negative left and right margin to overcome the paddings on the parent element. The downside of this is of course that the value supplied for the negative margin should match that of the value supplied for the parent padding. This makes changing the css a little tricker and more prone to mistakes.

case 3

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

The third case remains an easy fix as we simply need to single out the element which needs the extra spacing and apply a bigger margin to it. As you can see, thanks to the simplified css code in this solution there's no more problem with css specificity this time around. One less worry to keep us from sleeping at night.

The verdict

This solution shares many of the benefits of the previous solution but has simpler css declarations. This eliminates some issues with specificity and makes it a little bit easier to style things in IE6. The downside is that we go against one of our guidelines that makes changes in our css a bit more difficult and dangerous to handle.

The biggest problem is the clipped background we face when the parent element has none of the requirements to break the margin collapse. One fix is to apply a border to the parent element, another one is to float the parent element (and set it to a width of 100%). This last option won't work for this solution as there's already a padding defined on the parent element which will result in a width of 100% + padding. The only thing we can do is apply an overflow declaration that doesn't hurt our implementation.

The thing we haven't been able to fix is that we have to keep overruling the padding on the parent div in the second case. Let's try to fix this in our final solution. Stay tuned.