Friday, February 20, 2009

Technorati and CSS Descendants

As I was adding a hook for Technorati favorites, which is a clickable image generated by Technorati site (an img tag enclosed within an <a h-ref>), I ran into a problem. Although the green Technorati image showed up, it would eat up any bottom margin that I tried to assign to it through its immediate enclosing div, "techno-div". It seemed as if the bottom margin styling was being ignored!
.techno-div {
margin-bottom: 20px;
}

<div class='techno-div'>
<a href='http://technorati.com/faves?sub=addfavbtn&add=http://www.cssbakery.blogspot.com'>
<img alt='Add to Technorati Favorites' 
src='http://static.technorati.com/pix/fave/tech-fav-1.png'/>
</a>
</div>


So in order to debug, I turned the border on for the "techno-div" to see what was going on.
.techno-div {
margin-bottom: 20px;
border: 1px solid red;
}

The red border appeared as a flat line (see right sidebar in image below) which meant that this div had no height. Reason this was happening was because these two Technorati lines and their enclosing "techno-div" div had a grantparent div, "layoutlinks", that floats all its images to the left. The technorati image was being floated without my knowledge.
Sample Code
When you float an image, text will flow around it, but its parent and grandparent divs will not expand to contain it. Instead, the div will collapse to a size that it would have been if the image weren't there at all. In this case there really isn't any other space occupying content within techno-div, so with the image "floated away", the div collapses down to zero height, making the top and bottom borders into a single horizontal line!

So, why was my plain img tag being floated to the left? Turned out I had a float:left associated with a grandparent div of class "layoutlinks". Specifically the rule was:

.layoutlinks img { float: left; }

As seen in the snapshot image, if you Firebug the code, the IMG tag in TECHNO_DIV is a descendant of LAYOUTLINKS, meaning the descendant selector written as ".layoutlinks img" will target this img tag.

This is not the same thing as CSS inheritance where traits of a parent are passed down to a child.

So, how do you fix it so that the TECHNO_DIV no longer disappears? I could force the div to have a specific height, but instead I'll just override the float:left property that's coming from the .layoulinks img selector, and make it float:none instead:

.techno_div img { float: none; }

But wait, that selector has the same specificity as the original rule. So I could write this instead:

#techno_div img { float: none; }

But then I'd have to change the div to have an id of 'techno_div' rather than a class. Here's the approach I finally went with instead:

.layoutlinks .techno_div img { float: none; }

This is saying, a child IMG tag with a TECHNO_DIV as parent, and LAYOUTLINKS as grandparent. The border on TECHNO-DIV showed up this time, sizing up to its contents including the bottom margin on the image tag.
Sample Code

Post a Comment

Note: Only a member of this blog may post a comment.