IE inherited margin bug: form elements and hasLayout

Internet Explorer on Windows has a wide variety of rendering bugs. Many of these bugs can be worked around by giving affected elements the IE-specific "hasLayout" property and an extensive analysis of how and when this works is available. This article describes the opposite situation: an IE rendering bug that is triggered by elements having layout for which the workaround is to remove the hasLayout property.

The bug is that certain form input elements whose containing box has layout inherit the sum of the margins of all of their containing boxes. Unlike the the well known IE doubled float-margin bug, this one does not involve floats. There is a workaround but, so far, no magic-bullet CSS-only solution.

The Problem

Consider this sample code:

<form action="ignore">
<div style="width: 50%; margin-left: 5em; background-color: tan;">
  INPUT tag, type=text:<br />
  <input type="text" /><br />
  INPUT tag, type=checkbox:<br />
  <input type="checkbox" />
</div>
</form>

What should be displayed is a tan box, 50% of its parent's width wide, whose left edge is offset 5em from the left edge of its parent. Inside the box should be four lines of content, two text and two form elements, all flush against the left edge of the box.

Here is how it actually displays:

INPUT tag, type=text:

INPUT tag, type=checkbox:

If you are using IE/Win 6 or 7 (I have not yet tested it on other versions), notice that the left edge of the text input field (the second line) is pushed to the left. It inherited the left margin of its parent box because the parent has a width property, giving it hasLayout. Another example:

<form action="ignore">
<div style="margin: 2em;">
<div style="width: 50%; margin-left: 5em; background-color: tan;">
  INPUT tag, type=text:<br />
  <input type="text" /><br />
  INPUT tag, type=checkbox:<br />
  <input type="checkbox" />
</div>
</div>
</form>
INPUT tag, type=text:

INPUT tag, type=checkbox:

Here we see that the affected input element actually inherits the the sum of the left margins of all of its ancestors. Interestingly, it does not inherit the top or bottom margins.

The bug seems to occur for all INPUT types except checkbox, radio, and image as well as TEXTAREA elements but not for SELECT elements.

Workarounds

The problem only seems to occur when the direct parent of the INPUT element has hasLayout and any ancestor has margins. This leads to several possible workarounds:

  • Set a negative margin on the INPUT element equal to the sum of all of its parents' margins. This is fine for static sites but if you are using a CMS it is probably not possible without scripting. Keep in mind that only some INPUT element types are affected; assigning negative margins to checkbox, radio, or image inputs will break your layout.
  • Remove the margins from all ancestor elements. This is not particularly realistic.
  • Remove the hasLayout-granting style from the containing DIV. Since you presumably put that style there for a reason, this is also not particularly realistic.
  • Put inline text, a LABEL, or possibly any inline element at all immediately before the INPUT element. The fact that this solves the problem is probably why more people have not noticed it. Example:
    <div style="width: 50%; margin-left: 5em; background-color: tan;">
      INPUT tag, type=text, preceeded by inline text:<br />
      Text: <input type="text" />
    </div>
    INPUT tag, type=text, preceeded by inline text:
    Text:
  • Wrap the INPUT element in an unstyled SPAN, LABEL, or, in fact, any container element without a hasLayout-granting style. Example:
    <div style="width: 50%; margin-left: 5em; background-color: tan;">
      INPUT tag, type=text, wrapped in an unstyled SPAN:<br />
      <span><input type="text" /></span>
    </div>
    INPUT tag, type=text, wrapped in an unstyled SPAN:

If anyone knows a more general magic bullet for this, or other situations under which the bug occurs, please let me know.