Sunday, October 26, 2008

Don't Ever Put Block Inside Inline Elements

It's been incredibly busy at work so I haven't blogged at all in over two months.

I did discover something which may seem obvious to you, but is worth repeating. Don't ever put block elements inside inline elements. If you do, in most cases, nothing bad will happen. If you do, watch out. It's better not to do it. Here's what the W3C spec says.
Probably many of us do it anyways and it seems to work, but it's "go
to hell" incorrect. Block elements visually begin on a new line.
They can contain inline and other block-level elements ( div, p, ul,
etc. ). Inline elements visually don't begin on a new line. They
contain only text and other inline elements ( span, a, img, etc. ).

Take this example of the two Colas --

Visually, they look identical, but study the HTML and you'll see that they're constructed differently.

Block in Inline Element
<a href="#">
<img src="./captainColaHeadShot.jpg">
<div class="title">Cola the Yorkie BAD</div>
<div>Inline containing a block element. This is bad!</div>

Inline in Block Element
<a href="#">
<img src="./captainColaHeadShot.jpg">
<span class="title">Cola the Yorkie GOOD</span>
<span>Inline containing an inline element. This is good!</span>
So, what's the big deal? After all, it works. Well, sort of.

You'll need a couple of things to see what I mean. First, you'll need to run the example in Firefox 2.x or 3.x, but before you do that make sure you've installed Firebug. Now, using Firebug, inspect and edit the text "Inline containing a block element. This is bad!" that's found in the div. Just type in some additional text like "Hello world!" or just anything. Now, inspect the div. You'll notice that the text is now contained inside an anchor tag which is inside the div! What happened?

I'm not sure, but I think Firefox attempts to correct the HTML by putting an inline inside a block-level element ( here's a really good writeup on invalid markup funkiness among the browsers ). If you try the same thing ( editing the text for "Inline containing a block element. This is good!" ), you won't observe this problem. This is because the markup is correct -- we've got a block-level element containing an inline element.

So, in my real job I saw this funkiness happen. Every once in a blue moon on page refresh, the text would be found in an mysterious anchor tag creating an ugly "blown" up visual. Correcting the markup fixed this problem for good.

You might be wondering what's the difference between a block-level element ( <div> ) and using CSS to make an inline element a block-level element ( <span style="display:block;"> ).

If an element by default -- like a div -- is a block-level element then it cannot be placed inside an inline element. However, an inline element made into a block-level element via CSS can be placed inside an inline element. This is because the style that's applied is irrelevant to the correctness of the markup. In other words, styling is our stated intention for what the element should look like and that's completely separate from valid markup.

Have fun!