In a perfect world, we shouldn’t need to know anything about the
hasLayout property—after all, it’s an internal component of the Windows Internet Explorer rendering engine. Its effect, however, is far reaching, and has major consequences for the appearance and behavior of elements, affecting how an element bounds its content and reacts with its neighbors.
This topic is solely concerned with Internet Explorer for Windows.
What Is the hasLayout Property?
In Internet Explorer, an element is either responsible for sizing and arranging its own contents, or relies on a parent element to size and arrange its contents.
In order to accommodate these two different concepts, the rendering engine makes use of a property called
hasLayout that can have the values true or false for the element concerned. We say an element gains a layout or has a layout when the
hasLayout property has the value true.
When an element has a layout, it is responsible for sizing and positioning itself and possibly any descendant elements. In simple terms, this means that the element takes more care of itself and its contents, instead of relying on an ancestor element to do all the work. Therefore, some elements will have a layout by default, though the majority do not.
Elements that are responsible for arranging their own contents will have a layout by default, and include the following (this list is not exhaustive):
- body and html (in standards mode)
- table, tr, th, td
- input, button, file, select, textarea, fieldset
- frameset, frame, iframe
- objects, applets, embed
The main reasons Microsoft gives for the fact that not all elements have a layout by default are “performance and simplicity.” If all elements had a layout by default, a detrimental effect on performance and memory usage would result.
So why should any of us even care about the
hasLayout property? Because many Internet Explorer display inconsistencies which can be attributed to this property.
In most cases, the issues caused by elements that lack a layout are easy to spot: the content is often misplaced or completely missing. For example, when an element, such as a div, that doesn’t have a layout by default, contains floated or absolutely positioned content, it will often exhibit strange and buggy behavior. The types of strange behavior that can arise are varied, and include such behaviors as missing or misplaced content, or elements that fail to redraw fully while a window is moved or scrolled.
If you notice that a piece of your content appears and disappears, and sections of the page only get half-drawn, these are good indications that an element requires a layout. When the key element gains a layout, the problem miraculously goes away. In fact, 99% of the Internet Explorer CSS bugs you encounter on a daily basis can be fixed using a hasLayout fix in the correct place. A
hasLayout fix involves nothing more than declaring a CSS property that causes an element to gain a layout, when it wouldn’t ordinarily have a layout by default.
The simplest way for an element to gain a layout is for it to have a dimensional CSS property applied—for example, a
height. However, in situations where you don’t wish to apply a specific width or height to the element, there are several other CSS properties that, when you apply them to the element, will cause that element to gain a layout.
Those other properties are:
- display: inline-block
- height: (any value except auto)
- float: (left or right)
- position: absolute
- width: (any value except auto)
- writing-mode: tb-rl
- zoom: (any value except normal)
Internet Explorer 7 has some additional properties that cause an element to gain a layout (this is not an exhaustive list):
- min-height: (any value)
- max-height: (any value except none)
- min-width: (any value)
- max-width: (any value except none)
- overflow: (any value except visible)
- overflow-x: (any value except visible)
- overflow-y: (any value except visible)5
- position: fixed
Declaring any of these CSS properties will cause the element to gain a layout—assuming, of course, that the property is valid for the element concerned. For example, we can’t apply a height to inline elements unless the document is being run in quirks mode.
It’s not a good idea to give all elements a layout—not just because of the performance and memory issues already mentioned, but because a number of other unwanted CSS side effects will occur. For example:
Children of absolutely positioned or floated elements will not shrink to wrap their content when the child has a layout.
Static content positioned next to a float will not wrap around the float, but will instead form a rectangular block to the side of the float.
More examples of unwanted behavior are documented on the MSDN web site.
Debugging hasLayout Issues
If you notice that your web page is behaving strangely in Internet Explorer, try setting a CSS property for an element in order to cause it to gain a layout, and see if the problem vanishes.
Some skill is involved in identifying the correct element to which the property should be applied. With experience, it can become easy to identify the culprit—it’ll usually be a parent container for which no explicit width is set, or whose width is defined by margins alone. If this parent element contains floated or absolute elements, it’s likely to be the one causing the problem; the problems are likely to exist because it’s not taking proper care of its child elements.
A useful approach to debugging layout issues is to set the proprietary CSS property zoom to 1 for elements within the document, one at time, in order to isolate the element that’s causing the problem. If you set the property on an element, and the issue is resolved, you know you’re on the right track. The zoom property is useful because, as well as being a property that triggers an element to gain a layout, in most cases, setting it will not alter the look of the page in any other way (apart from possibly fixing the bug that you’re experiencing). A process of elimination can be used to narrow the problem down quite quickly.
Once you have found the element that’s causing the problem, you can apply the necessary fix. The preferred approach is to set one or more dimensional CSS properties on the element. However, if dimensions can’t be applied normally, a workaround must be employed.
For Internet Explorer 7, the best approach is to set the min-height property to 0; this technique is harmless, since 0 is the initial value for the property anyway. There’s no need to hide the property from other browsers—which is definitely not the case with our next suggestion!
The standard approach for triggering an element to gain a layout in Internet Explorer 6 and earlier versions is to set the height property to 1%, as long as the overflow property is not set to anything except visible. This approach exploits a bug in these browser versions whereby if the overflow property is set to the default value of visible, the height of a containing box will expand to fit its contents regardless of the height property’s value. However, most other browsers will respect the height value of 1%, which is usually not what you want them to do, so this declaration will need to be hidden from all other browsers.
In previous years, the technique of setting height to 1%, and hiding the declaration from all browsers except Internet Explorer 6 and earlier versions, was known as the Holly hack. These days, the recommended method for specifying CSS declarations for Internet Explorer only is through the use of conditional comments.
The good news is that Internet Explorer 7 is a lot more robust than previous versions, and many (though not all, unfortunately) of the issues concerning layout have disappeared—you’ll need far fewer fixes than you might have in previous versions of the browser. For more information about the layout issue, see “On Having Layout” at the Satzansatz web site.