The Internet Explorer hasLayout Property
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.1
When an element has a layout, it is responsible for sizing and positioning itself and possibly any descendant elements.2 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):
bodyandhtml(in standards mode)table,tr,th,tdimghrinput,button,file,select,textarea,fieldsetmarqueeframeset,frame,iframeobjects,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.3
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 width or 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-blockheight: (any value exceptauto)float: (leftorright)position:absolutewidth: (any value exceptauto)writing-mode:tb-rlzoom: (any value exceptnormal)4
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 exceptnone)min-width: (any value)max-width: (any value exceptnone)overflow: (any value exceptvisible)overflow-x: (any value exceptvisible)overflow-y: (any value exceptvisible)5position: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.
Footnotes
1 Once an element has a
layout, the hasLayout property can be queried by the
rendering engine or through scripting.
2 If a descendant element also has a layout it is responsible for sizing itself and any descendants, but it is positioned by the ancestor element’s layout.
3 A detailed description of some examples of these behaviors can be found at the Position Is Everything web site at http://positioniseverything.net/explorer.html.
4 zoom and
writing-mode are proprietary Internet Explorer CSS
properties, and will not pass CSS validation.
5 overflow-x and
overflow-y are proposed property names for CSS3,
but have been proprietary CSS properties in Internet Explorer since
version 5.
User-contributed notes
- ID:
- #8
- Date:
- Sat, 25 Jul 2009 18:46:42 GMT
Indeed Paul, zoom:1 is by far the easiest - & thanks for the theory lesson :)
my post, the quoted comments which I think were cut? Were written before inline-block was more widely supported - namely Firefox although IE6/7 still doesn't support it properly, without this trip, on block level elements. Hence the need to trip the display property back to what it should be (either block or inline).
Note: inline-block; added to an element alone is not enough to make it act like a block if that is the required behaviour from the layouted element. Nor is it safe to assume default inline behaviour in all cases. see: http://www.brunildo.org/test/InlineBlockLayout.html, so again that was/is my reasons for tripping it back to what it should be
inline-block added to a block level element will mean the element will no longer auto fit its parent. So tripping it back just keeps all browsers/stylesheets on an even keel without needing to calculate specific widths or heights or guess how different browsers (or indeed IE) would handle the proper behaviour of inline-block itself
The last rule you show will of course set hasLayout by order of the cascade, but leaves the display of the element as an inline-block, that may be perfectly fine as you say, but check previous link, especially now with the x-browser support as good as it is - so advice is, use zoom: 1; or if using tripswitch, then still 'trip' it back to what you want please
I am a bit conscientious about this behaviour because I never wittingly invented a "hack", I just discovered a behaviour by accident. I have always advocated if using for hasLayout trigger to 'trip it back' and to comment it to that effect too, to avoid unexpected things happening (e.g. people copy paste, doesn't work as expected, they blame person who told them that.. in this case that would be you, and we can't have that!) - http://onhavinglayout.fwpf-webdesign.de/hack_management/#method-comparison - picked it up why I still defend it ;)
I'm not sure that having different rules in the same ruleset fails to make it work is like the old !important hack, but instead is merely the cascade working properly, i.e. it ignores the first declaration. Why it works in different rulesets I presume is because it is actually applying the first rule (rather than ignoring it) then subsequently overruling with the second. (i.e. setting the hasLayout part of it but not overruling it as it can't be changed once set)
Authors should note that width and height would be needed to make inline-blocks act like a proper block (fill its parent) in which case width and height both trigger hasLayout too so if the original element was a actual inline element the trip back to display:block; is possibly simpler than calculating and carrying widths/heights through especially if borders/padding involved. If it's a block level element then width/height can be used by themselves to trigger haslayout, so there would be no need to trip the display property at all ** ;)
LOL, after all that, zoom: 1; is easier of course in a conditional stylesheet, and is the one I would use mostly. If you are already using the Holly Hack in a conditional stylesheet, and like it because you know it - it's still advisable to change it to zoom:1; as it has proved unstable in rare cases see: http://www.brunildo.org/test/relayout.html
[** aside]
The inline-block "tripswitch" is also a method to force inline-block to work on block level elements in IE6/7 which is how I would mainly use it, it just has the benefit of adding hasLayout at the same time, which is normally needed when doing this anyway ;)
In short the inline-block (tripswitch) method is as safe as the zoom method, but the tripswitch validates and has other uses too, namely being able to use inline-block on block level elements in IE6/7, which I think is going to prove much more useful going forward
- ID:
- #7
- Date:
- Sat, 16 May 2009 01:45:08 GMT
"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."
The idea is clear, but the grammar could read more clearly. Maybe you mean something like "many Internet Explorer browsers display..." or "Because Internet Explorer often displays..."
- ID:
- #6
- Date:
- Mon, 25 Aug 2008 18:14:37 GMT
re: comments below:
"----------------
The following should cause A elements to gain a layout:
a {display:inline-block;}
a {display:block;}
But this would not:
a {
display:inline-block;
display:block;
}
-------------"
For elements that are naturally inline such as a elements then all that is needed to trigger "haslayout" is to use one of the properties that trigger "haslayout" (as listed in the reference above). However the "trigger" must be a property that applies to inline elements which is why you can't use width or height as a trigger on inline elements.
An inline element can simply have zoom:1.0 applied and no other properties need be supplied in separate rules. The inline-block value also applies to inline elements and is also a trigger for "haslayout" so for inline elements then display:inline-block can be used and no other rules are required.
There is no need to re-state the display:block in a separate rule as it is not needed here at all.
This will do just fine.
a {display:inline-block;}
or even
a{zoom:1.0}
The reason that the following example fails to gain "haslayout" is probably the same reason that the "!important hack" works and is used to target IE.
a {
display:inline-block;
display:block;
}
IE only seems to apply the latter property/value it sees when there's more than one property with the same name in the same rule. The element never gets a chance to "gain haslayout" because IE only sees and applies the display:block in that rule.
Therefore this rule will still apply "haslayout":
a {
display:block;
display:inline-block;
}
IE ignores the display:block and only applies the display:inline-block
That's the theory anyway.
- ID:
- #4
- Date:
- Tue, 04 Mar 2008 10:49:27 GMT
Typo:
"...proprietary CSS property zoom to 1 for elements within the document, one at time, in order..."
"one at time" should be "one at a time"
Covering the IE haslayout property, some bugs it can cause, and how to go about fixing them is very helpful. Thanks! :)
- ID:
- #3
- Date:
- Fri, 22 Feb 2008 18:56:36 GMT
"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."
Omit the word "which" in the second sentence.
Add a note
To post a note on this topic, please log in with your SitePoint username and password. If you don't have an account yet, you can create a new account for free.