White-space lines in Internet Explorer caused by elements that have layout
Sometimes pages rendered in Internet Explorer (IE) have unexpected white-space strips (horizontal lines) which are neither added intentionally by the web designer nor are these white-space blocks present when the page is viewed in another web browser. This article explains one of the features/bugs in IE that cause this superfluous white-space. Also in this article we show a couple of workarounds which allow us to avoid this whitespace effect.
When does the whitespace appear?
The whitespace effect appears in all modern versions of Internet Explorer (IE5, IE6, IE7 and IE8) when there is a container tag (e.g. DIV) which has layout (see the next section for a description of the layout the way IE understands it). In this case the height of the container is greater than or equal to the line box height computed for that container. For details on the computation of this value see the corresponding section in the CSS specification.
Let's take this sample code:
<div style="font-size: 30px; border: 1px solid black; height: 0px;"></div>
We have set the height to 0px so we expect the DIV to appear as a horizontal line which is 2 pixels thick (one pixel for the top border and another pixel for the bottom border). We have not set any width for the DIV so it should occupy the whole available horizontal space. And indeed, this is how it appears in browsers other than IE, e.g. Firefox (FF) :
However in IE, the same code will generate the following box:
Even though the container DIV is empty, IE still allocates vertical space for a line of text. The reason for this strange behavior is that in IE the DIV box has layout because of the "height: 0px" CSS property. The layout causes the box to have a minimal height equal to its line-height, which in the absense of any explicit setting is equal to the font-size for that box which we have set to 30 pixels. See next section for an explanation of the element layout in IE.
Strictly speaking it is not a white space bug but rather a dimensional bug which causes IE to calculate incorrectly the heights of some HTML elements. However this bug often causes unwanted white spaces in web pages so that is why we call it a "white-space bug".
What is layout (the way Internet Explorer understands it)?
In Internet Explorer each HTML element has a non-standard flag called layout, which affects the size of the element as well as the sizes and positions of its child elements (if any). Basically the size and position of an element without layout is determined by that element's nearest ancestor that has layout. When an element has layout it is affected by its ancestors to a much lesser degree than elements without a layout.
We can check if an element has layout by checking a property in element's currentStyle. The property is called hasLayout and it is read-only. The following code shows how to read the hasLayout property in Internet Explorer.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <body onload="alert (document.getElementById ('test_div').currentStyle.hasLayout)"> <div id="test_div" style="font-size: 30px; border: 1px solid black; height: 0px;"></div> </body> </html>
If you try running this example in IE, it will display an alert box with the value "true" in it. Try removing the height: 0px CSS property from the DIV definition and the displayed value will change to false.
If you are interested in further details about element layout in Internet Explorer you may want to check the MSDN documentation, as well as this excellent article on the inner details of hasLayout.
What possible workarounds are there for this layout bug?
As we already saw in the previous section, simply setting the element height to zero (or any other fixed value) does not help us solve this problem, because IE simply extends the DIV height to the computed line-height. Neither does overflow: hidden or any other overflow value help.
One possible approach is to modify the HTML code or CSS style in such a way that the element's hasLayout property would be computed to false. However there is no known way to make hasLayout = false for a given element through scripting - once it has been set to true by IE it cannot be changed back. This means that if an HTML element has layout from the beginning, we need to use a different method to solve the whitespace issue. MSDN provides a list of HTML element types for which hasLayout is always true: images, tables, table rows, table cells, hr, input elements, marquee, framesets, frames, objects, applets, plugins. So if you need to solve the whitespace issue with one of these elements, you need to either replace the element with some other HTML tag which by default does not have layout or you can resort to a different method.
Also there is a list of CSS properties and values, assigning which to an element will give it layout:
- display: inline-block
- height: any value. However see MSDN for details on the effect of backwards compatibility mode and CSS "display" property.
- float: left or right
- position: absolute
- width: any value. However see MSDN for details on the effect of backwards compatibility mode and CSS "display" property.
- -ms-writing-mode: tb-rl
- zoom: any value different from normal
If you want an element without a layout to stay layoutless, then you need to avoid assigning any CSS properties to it that would make it gain layout. In some cases it is pretty easy, for example in our sample code we can get rid of the DIV layout just by removing the height: 0px CSS property. In other cases however it is not so easy to avoid using some of these CSS properties/values.
When you cannot avoid using an HTML tag or CSS property that would give the element layout, you can resort to another workaround. Remember that the minimal element height is equal to its line-height, so even if we can not get rid of the hasLayout = true setting, we still can decrease the line-height to zero, thus effectively eliminating the whitespace:
<div style="font-size: 30px; border: 1px solid black; height: 0px; line-height: 0px;"></div>
Setting the line-height to zero means that any text inside the container will not be visible, but usually it is not a problem, because the unwanted whitespace areas do not have any text content anyway.