views:

20036

answers:

11

I'm in the process of doing some advance IE8 testing, and it seems that the old technique of using "margin: 0 auto;" doesn't work in all cases in IE8.

The following piece of HTML gives a centered button in FF3, Opera, Safari, Chrome, IE7, and IE8 compat, but NOT in IE8 standard:

<div style="height: 500px; width: 500px; background-color: Yellow;">
    <input type="submit" style="display: block; margin: 0 auto;" />
</div>

(As a work-around I can add an explicit width to the button).

So the question is: which browsers are correct? Or is this one of those cases where the behaviour is undefined?

(My thinking is that all the browsers are incorrect - shouldn't the button be 100% width if it's "display: block"?)

UPDATE: I'm being a dunce. Since input isn't a block-level element, I should have just contained it within a div with "text-align: center". Having said that, for curiosity's sake, I'd still like to know whether the button should or shouldn't be centered in the example above.

FOR THE BOUNTY: I know I'm doing odd things in the example, and as I point out in the update, I should have just aligned it center. For the bounty, I'd like references to the specs that answer:

  1. If I set "display: block", should the button be width 100%? Or is this undefined?

  2. Since the display is block, should "margin: 0 auto;" center the button, or not, or undefined?

+1  A: 

shouldn't the button be 100% width if it's "display: block"

No. That just means it's the only thing in the space vertically (assuming you aren't using another trick to force something else there as well). It doesn't mean it has to fill up the width of that space.

I think your problem in this instance is that the input is not natively a block element. Try nesting it inside another div and set the margin on that. But I don't have an IE8 browser to test this with at the moment, so it's just a guess.

Joel Coehoorn
A: 

If I remember correctly you have to specify the width of all elements, that you try to center using margin:0 auto. I think therefore IE8 renders it correctly.

Georg
A: 

"margin: 0 auto" only centers an element in IE if the parent element has a "text-align: center".

Chris
A: 
  1. Assuming margin: 0 auto then the element should be centered, but the width is left as-is--whatever it is calculated to be, disregarding any margin settings.
  2. If you set the <INPUT> tag to display:block, then it should be centered with margin: 0 auto.

See Visual formatting model details - calculating widths and margins from the CSS 2.1 specs for more details. Relavent bits include:

In a block formatting context, each box's left outer edge touches the left edge of the containing block.

and

When the total width of the inline boxes on a line is less than the width of the line box containing them, their horizontal distribution within the line box is determined by the 'text-align' property.

finally

If 'width' is set to 'auto', any other 'auto' values become '0' and 'width' follows from the resulting equality.

If both 'margin-left' and 'margin-right' are 'auto', their used values are equal. This horizontally centers the element with respect to the edges of the containing block.

Mufasa
+13  A: 

It is a bug in IE8.

Starting with your second question: “margin: 0 auto” centers a block, but only when width of the block is set to be less that width of parent. Usually, they get to be the same. That is why text in the example below is not centered.

<div style="height: 100px; width: 500px; background-color: Yellow;">    
    <b style="display: block; margin: 0 auto; ">text</b>
</div>

Once the display style of the b element is set to block, its width defaults to the parents width. CSS spec 10.3.3 Block-level, non-replaced elements in normal flow describes how: “If 'width' is set to 'auto', any other 'auto' values become '0' and 'width' follows from the resulting equality.” The equality mentioned there is

'margin-left' + 'border-left-width' + 'padding-left' + 'width' + 'padding-right' + 'border-right-width' + 'margin-right' = width of containing block

So, normally all autos result in a block width being equal to the width of containing block.

However, this calculation should not be applied to INPUT, which is a replaced element. Replaced elements are covered by 10.3.4 Block-level, replaced elements in normal flow. Text there says: “The used value of 'width' is determined as for inline replaced elements.” The relevant part of 10.3.2 Inline, replaced elements is: “if 'width' has a computed value of 'auto', and the element has an intrinsic width, then that intrinsic width is the used value of 'width'”.

I guess that the scenario CSS cares about is IMG element. Stackoverflow logo in this example will be centered by all browsers.

<div style="height: 100px; width: 500px; background-color: Yellow;">    
    <img style="display: block; margin: 0 auto; " border="0" src="http://stackoverflow.com/content/img/so/logo.png" alt="">
</div>

INPUT element should behave the same way.

buti-oxa
Thanks, I didn't know about replaced elements. I try to read the spec, but it just sends me to sleep.
stusmith
+1  A: 

Yes, you can read the spec a hundred times, and combine different bits and pieces until you have an interpretation that feels right – but that's exactly what the browser vendors did and that's why we're in the situation we are today.

In essence, when you apply a width of 100% to an element it should extend to 100% of it's parent's width, if that parent is a block element. You can't center it anymore with margin: 0 auto; then since it already takes up 100% of the available width.

To center anything with margin: 0 auto; you need to define an explicit width. To center an inline element, you can use text-align: center; on the parent element, although this could have unwanted side-effects if the parent has other children.

Wolfr
+5  A: 

Form controls are replaced elements in CSS.

10.3.4 Block-level, replaced elements in normal flow

The used value of 'width' is determined as for inline replaced elements. Then the rules for non-replaced block-level elements are applied to determine the margins.

So the form control should not be stretched to 100% width.

However, it should be centered. It looks like an ordinary bug in IE8. It centers the element if you set specific width:

<input type="submit" style="display: block; width:100px; margin: 0 auto;" />
porneL
A: 

As explained by buti-oxa this is a bug with the way IE8 handles replaced elements. If you don't want to add an explicit width to your button then you can change it to an inline-block and center align the contents:

<div style="height: 500px; width: 500px; background-color: Yellow; text-align: center;">
  <input type="submit" style="display: inline-block;" />
</div>

If you want this to work in older versions of Mozilla (including FF2) that don't support inline-block then you can add display: -moz-inline-stack; to the button.

Simon Dyson
+2  A: 

As far as this being a "bug" with relation to the spec; it isn't. As the author of the post questions, the behaviour for this would be "undefined" since this behaviour in IE only happens on form controls, as per spec:

CSS 2.1 does not define which properties apply to form controls and frames, or how CSS can be used to style them. User agents may apply CSS properties to these elements. Authors are recommended to treat such support as experimental.

( http://www.w3.org/TR/CSS21/conform.html#conformance )

Cheers!

A: 

One more time: we all hate IE!

<div style="width:100%;background-color:blue;">
    <div style="margin:0 auto;width:300px;background-color:red;">
        Not Working
    </div>
</div>

<div style="width:100%;background-color:green;text-align:center;">
    <div style="margin:0 auto;width:300px;background-color:orange;text-align:left;">
        Working, but dumb that you have to use text-align
    </div>
</div>
zeroasterisk
+1  A: 

Adding <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&gt; solves the issue

Pal