hasLayout.net

Text-Align Bug

Affected Versions

This bug affects: IE7

Symptoms

text-align property affects block-level elements

Date of the Tutorial

Fri Jul 17 00:34:27 2009

Description

Here is the bug that might ring a bell right away or may completely leave you clueless, especially if you didn't "just write" the code.

Some of you may recall how you would use text-align property to center block-level elements in IEs below version 6 due to the broken auto value handling with . The reason it worked is because was also broken and instead of aligning only inline-level content it affected block-level elements as well.

The margin bug was fixed in however text-align bug was left forgotten and still lives in IE7.

Demo

Give me the aligns!

Oh noes!

Give me the aligns!

Oh noes!

HTML Code:
<div id="container1">
    Give me the aligns!
    <p>Oh noes!</p>
</div>
<div id="container2">
    Give me the aligns!
    <p>Oh noes!</p>
</div>
CSS Code:
#container1 { text-align: center; }
#container2 { text-align: right; }
    p { width: 50%; }

Our demo consists of two containers #container1 and #container2, both of which have text-align applied to them: #container1 { text-align: center; } #container2 { text-align: right; }; both of which have plain text (inline-level content) and a paragraph (block-level content) inside.

In standards compliant browsers everything looks fine, all of text is either centered or right aligned. For those wondering why text inside paragraphs (<p> element) is also affected I'd like to remind you that text-align property is inherited.

What you will note in all current version of Internet Explorer is that our paragraphs are aligned themselves; text-align on our containers affected block-level elements, which it shouldn't.

Solutions

Below are solutions for the above bug ordered by the solution type.

Solution (Clean Markup Solution)

Date of the Solution

Fri Jul 17 01:48:23 2009

Fixed Versions

all of the affected

Description

I can't think of too many cases where you would have plain text with a block-level sibling element. Thus, this solution may not only fix the Text-Align bug but also improve the semantic structure of your document. The idea of the solution is to encapsulate your plain text, or rather your inline-level content which text-align should affect, inside an appropriate element. If you don't know HTML as the back of your hand I suggest you familiarize yourself with HTML elements. The HTML Elements Best Practice Sheet may come in handy as well.

Give me the aligns!

Oh noes!

Give me the aligns!

Oh noes!

HTML Code:
<div id="container1">
    <p id="fixed1">Give me the aligns!</p>
    <p>Oh noes!</p>
</div>
<div id="container2">
    <p id="fixed2">Give me the aligns!</p>
    <p>Oh noes!</p>
</div>
CSS Code:
p { width: 50%; }
#fixed1,
#fixed2 {
    width: auto;
    text-align: center;
}
#fixed2 { text-align: right; }

We chose <p> element for our text that we want to align, I will not argue about semantics, this is just an example so <p> will do just fine.

Regarding CSS code, note that we no longer have text-align neither on #container1 nor on #container2, we moved those to #fixed1 and #fixed2 which are the extra elements we have added. If you don't understand why #fixed1 gets text-align: center and #fixed2 gets text-align: right I suggest you read up on cascade; same goes for width: auto declaration which is needed in our example because we have p { width: 50%; } already.

Since we have localized the effect of text-align property the bug does not appear anymore because neither #fixed1 nor #fixed2 have any block-level elements in them.

Solution (Clean Solution)

Date of the Solution

Fri Jul 17 01:29:24 2009

Fixed Versions

all of the affected

Description

If you are not perfectly sure that you have semantic markup, chances are that you would want to read the "Clean Markup Solution" instead.

This fix uses only two rules (possibly even one) in your main stylesheet and is suitable for rare cases when you have a text node as a sibling of a block-level element and you want to apply text-align to that text. Let's take a look:

Give me the aligns!

Oh noes!

Give me the aligns!

Oh noes!

HTML Code:
<div id="container1">
    Give me the aligns!
    <p>Oh noes!</p>
</div>
<div id="container2">
    Give me the aligns!
    <p>Oh noes!</p>
</div>
CSS Code:
/* contain float - irrelevant to the bug, but something you might need to do */
div {
    overflow: hidden; 
    display: inline-block;
}
div { display: block; } /* restore original display, IE hasLayout method */
/* END of float containing */
#container1 { text-align: center; }
#container2 { text-align: right; }
    p {
        width: 50%;
        float: left;
    }

Let me explain the idea of the fix, since the code has some extra bits that are not exactly relevant. What fixes the bug is the float, simple as that. Yes, this fix is not always possible to implement, if that's the case you may want to try the "Clean Markup solution" for this bug instead.

Besides p { float: left; } and the rest of the code from the demo you will notice a block of CSS code marked with float containing Microsoft, it is there because we are floating the descendants (<p>s), thus we need to contain them in the parent elements. The technique is known as float containment and is outside the scope of this tutorial. I may note that the div { display: inline-block; } div { display: block; } is a method to give "layout" in IE which may be not suitable or not needed in your situation.