hasLayout.net

No Auto-Margin Center on Buttons Inconsistency

Affected Versions

This bug affects: IE8

Symptoms

Button-like elements do not get centered when { display: block; margin-left: auto; margin-right: auto; } applied on them and `width` is not explicitly set

Date of the Tutorial

Wed Aug 19 10:22:23 2009

Description

Here's a bug I found on Gérard Talbot's IE8 Bug Collection Page, although, I would like to amend the bug's description and say that this bug only applies to buttons and not all inline replaced elements; i.e. ' element"><button> and ' element"><input> of type="button" and type="submit". Furthermore, this is not a bug as far as spec conformance goes, since 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. However, this bug was not present in earlier versions of IE and sane browsers render the buttons centered, so, let's take a look:

Demo

The demo is available on a separate page

HTML Code:
<form action="">
<div>
    <button>This button should be centered</button>
    <input type="button" value="This button should be centered">
    <input type="text">
    <input type="checkbox">
    <input type="radio">
    <input type="submit" value="This button should be centered">
    <input type="file">
    <select><option>test</option></select>
</div>
</form>
CSS Code:
button, select, input {
  display: block;
  margin-left: auto;
  margin-right: auto;
  width: auto;
}

In sane browsers as well as IE7 the ' element"><button> element in the demo and buttoned ' element"><input> controls (type="submit" and type="button") will be centered as all the other form controls on that demo. IE8 decided that it was a bad idea and the buttons are left aligned despite margin-left and margin-right set to value auto along with display set to block (buttons are replaced and therefore have intrinsic dimensions on them).

Solutions

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

Solution (Clean Solution)

Date of the Solution

Wed Aug 19 10:43:21 2009

Fixed Versions

All of the affected

Description

This is rather a solution that avoids the "question asked"; however, it fixes the bug and may be a feasible solution if you have just a couple of buttons. Let's have a look:

Fixed demo is available on a separate page

HTML Code:
<form action="">
<div>
    <button>This button should be centered</button>
    <input type="button" value="This button should be centered">
    <input type="text">
    <input type="checkbox">
    <input type="radio">
    <input type="submit" value="This button should be centered">
    <input type="file">
    <select><option>test</option></select>
</div>
</form>
CSS Code:
button, select, input {
  display: block;
  margin-left: auto;
  margin-right: auto;
  width: auto;
}
button,
input[type="submit"],
input[type="button"] {
    width: 20em;
}

The markup stayed the same and what I simply did in CSS is added explicit width to the button-like form controls. If you are unhappy with the way this explicit width makes the buttons render in other browsers, simply use conditional comments to apply this fix.

The drawback of this solution is that you would have to figure out the width of every button - in my demo all three buttons have the same text on them and that is why I applied the same width to all of them.

Solution (JavaScript Solution)

Date of the Solution

Wed Aug 19 11:17:13 2009

Fixed Versions

All of the affected

Description

If you have a billion of buttons and other solutions are not applicable, you may want to consider this JavaScript solution. Note: I am well aware that it is possible to do the same fix by putting JS code into IE proprietary expression() and keeping it in CSS file; however, those cause more evil than good by executing thousands of times a pop - just a warning, do whatever you see fit. Let's have a look at the demo:

Fixed demo is available on a separate page

HTML Code:
<form action="">
<div>
    <button>This button should be centered</button>
    <input type="button" value="This button should be centered">
    <input type="text">
    <input type="checkbox">
    <input type="radio">
    <input type="submit" value="This button should be centered">
    <input type="file">
    <select><option>test</option></select>
</div>
</form>
CSS Code:
button, select, input {
  display: block;
  margin-left: auto;
  margin-right: auto;
  width: auto;
}
JavaScript Code:
<script type="text/javascript">
    var buttons = document.getElementsByTagName('button');
    for ( var i = 0; i < buttons.length; i++ ) {
        buttons[i].style.width = buttons[i].offsetWidth + 'px';
    }
    var inputs  = document.getElementsByTagName('input');
    for ( var i = 0; i < inputs.length; i++ ) {
        if ( inputs[i].type == 'button' || inputs[i].type == 'submit' ) {
            inputs[i].style.width = inputs[i].offsetWidth + 'px';
        }
    }
</script>

The markup and CSS stayed the same. What our JS code is doing is finding all the button-like form controls, figuring out their width and setting that width as a CSS style. No brainer.

Solution ()

Date of the Solution

Wed Aug 19 10:22:41 2009

Fixed Versions

All of the affected

Description

This workaround solution would probably defeat the reason of why you setting { display: block; margin: 0 auto;} on the buttons; however it may shed some light. Let's see what we have.

Fixed demo is available on a separate page

HTML Code:
<form action="">
<div>
    <button>This button should be centered</button>
    <div class="ie_fix">
        <input type="button" value="This button should be centered">
    </div>
    <input type="text">
    <input type="checkbox">
    <input type="radio">
    <div class="ie_fix">
        <input type="submit" value="This button should be centered">
    </div>
    <input type="file">
    <select><option>test</option></select>
</div>
</form>
CSS Code:
button, select, input {
  display: block;
  margin-left: auto;
  margin-right: auto;
  width: auto;
}
.ie_fix {
    text-align: center;
}
.ie_fix input[type="submit"],
.ie_fix input[type="button"] {
    display: inline-block;
}
Conditional Comments Code:
<!--[if IE 8]>
<style type="text/css">
    button { display: table; }
</style>
<![endif]-->

Let's bread this fix down. First of all, what we are doing to ' element"><input> type="button" and type="submit" can also be used to fix the ' element"><button>; I'm only showing a different fix for a ' element"><button> becase it doesn't require extra markup, although, doesn't work on due to yet another bug.

On ' element"><button> I've set display property to value table. This makes it centered, however, breaks the centering in Opera and that is the reason why this fix is inside IE8 targeted conditional comments.

For button-lookin' ' element"><input>s the fix is more complex. What I did is added an extra ' element"><div> around each one, set to value center on that ' element"><div> and set the ' element"><input>s those fixer ' element"><div>s contain to { display: inline-block; } - this would allow you to still be able to change their widths if the need would arise, yet makes them responsible to text-align.