This is a draft; a work in progress.
- This version:
- Rev. 4 2005-08-20
- Table of content
A lot of Internet Explorer's rendering inconsistencies can be fixed by giving an element “layout.” John Gallant and Holly Bergevin classified these inconsistencies as “dimensional bugs,” meaning that they can often be solved by applying a width or height. This leads to a question of why “layout” can change the rendering of and the relationships between elements. The question, albeit a good one, is hard to answer. In this article, the authors focus on some aspects of this complicated matter. For more thorough discussions and examples, please refer to the links provided.
hasLayout – A Definition
“Layout” is an IE/Win proprietary concept that determines how elements, in analogy to a window, draw and bound their content, interact with and relate to other elements, and react on and transmit application/user events.
Microsoft developers decided that box-type elements should be able to acquire a “property” (in an object-oriented programming sense) they referred to as
layout, or alternatively,
hasLayout is probably neither a property or even a behavior, but rather an engine-inherent rendering concept which gives a quality to an element.
This rendering quality can, in fact, be irreversibly triggered to
true by some CSS properties, and some HTML elements have “layout” by default.
We speak of an element “having layout” or “gaining layout” or say that an element “has layout” when we assume that the Microsoft-proprietary property
hasLayout is set to
true. A “layout element” can be any element which has layout by default or has gained layout by setting the appropriate CSS property.
Giving or applying “layout” to an element that does not have it by default involves setting a CSS property that triggers
hasLayout = true for the element in question. See Default Layout Elements and Properties for these listings. There is no way to set
hasLayout = false other than to remove the CSS property that caused
hasLayout = true in the first place.
The Hand We've Been Dealt
hasLayout problem affects designers (and coders) at all experience levels. Layout has unusual and hard to predict effects on the display behavior of boxes that “have” layout, as well as implications for child elements within the boxes.
Consequences of an element having, or not having “layout” can include:
- Many common IE float bugs.
- Boxes themselves treating basic properties differently.
- Margin collapsing between a container and its descendants.
- Various problems with the construction of lists.
- Differences in the positioning of background images.
- Differences between browsers when using scripting.
The above list is brief and incomplete. This article attempts to more thoroughly describe issues encountered by the application of “layout” or the lack of it.
Where Layout Comes From
Unlike standard properties, or even proprietary CSS properties available in different browsers, layout is not directly assigned via CSS declarations. In other words, there is no “layout property.” Certain elements automatically “have layout” and it is quietly added when various CSS declarations are made.
Default layout elements
The following elements appear to have layout by default, even if the MSDN
documentation is not clear about this.
<input>, <select>, <textarea>, <button>
<iframe>, <embed>, <object>, <applet>
We have tested most of these elements by applying the MS
The following CSS property/value pairs will, if applied, allow an element to gain layout.
- Refers to its containing block, and that's where some problems begin.
- The float model has a lot of quirks due to some aspects of a layout element.
Sometimes a cure when the element is at inline level and needs layout. Applying layout is probably the only real effect of this property. The “inline-block behaviour” itself can be achieved in IE, but
IE/Win: inline-block and hasLayout.
width: any value
- This is often an implicit fix, more often the trigger when hasLayout does things wrong.
height: any value
- height: 1% is used in the Holly Hack.
zoom: any value (MSDN)
- MS proprietary, does not validate.
zoom: 1 can be used for debugging.
writing-mode: tb-rl (MSDN)
- MS proprietary, does not validate.
Notes on elements at inline level
For inline elements (either inline by default like
span, or having
hasLayout in IE 5.x and IE 6 in quirksmode only. As of IE6, when the browser is in “standards-compliance mode” inline elements will ignore the width and height properties, and setting the width and height properties will not cause the element to have layout.
zoom always triggers
hasLayout , but it's not supported in IE5.0.
Elements having both “layout” and
display: inline behave in a similar way as what the standards say about inline-block: they flow horizontally like words in a paragraph, are sensitive to vertical align, and apply a sort of shrink-wrapping to their content. As soon as the inline elements have layout, they act as inline-block, this is an explanation why, in IE/Win, inline elements can contain and hold block-level elements with less problems than in other browsers, where
display: inline remains inline.
The hasLayout script property
We have chosen to refer to
hasLayout as a “script property” in order to distinguish it from the CSS properties we are familiar with.
Note once an element has layout, there is no way to set
hasLayout = False.
The hasLayout-property can be used to
check if an element has layout: If it has an
id, simply writing in
the IE5.5+ address bar
tests its state.
Another thing to consider is how “layout” affects scripting. The
clientHeight properties always return zero for elements without “layout.” This can be confusing to new scripters and is different to how Mozilla browsers behave. We can use this fact to determine “layout” for IE5.0: If the
clientWidth is zero then the element does not have layout.
The following hacks to trigger
haslayout have been well tested in IE6 and lower. Future versions of IE might react differently. We will revisit this when new versions of this browser are publicly available.
John Gallant and Holly Bergevin published the Holly hack in 2003:
zoom: 1; gives layout in IE5.5+ to any element (including inline elements), but it has no effect in IE5.0
- No known side effects (inline elements behave like inline-block, though).
- If validation is required,
zoom must be hidden via conditional comments.
While we think “future proof” is a contradiction in terms, we strongly suggest the webdesigner “plays for sure” and review her pages for explicit and implicit “hacks” and use conditional comments to serve those hacks to the appropriate browser version.
A short note about IE Mac.
IE Mac and IE for Windows are two different animals, living in separate parts of the zoo. Each has its own rendering engine, and IE Mac doesn't know about the “hasLayout” behaviour (or
contenteditable) in any way. The IE Mac rendering engine tend to be rather standard compliant, with i.e.
height being treated as
height, as it should. Hacks and workarounds for the “hasLayout” problems (especially when using the
width properties) will often have rather detrimental effects on IE Mac, and should be hidden from that browser. More on IE Mac problems can be found at the IE Mac, bugs and oddities pages.
In the MSDN, there are very few pages related to the hasLayout property, and less is explained how having layout correlates with the visual formatting model of IE.
Back in IE4, nearly every element had sort of layout, except for simple inline elements not positioned absolutely and without a dimension (MSDN). And in this early layout concept, there were “layout properties” like
border, margin, padding, which can't be applied to such a simple inline element. In other words, “having layout” was just another term for roughly: “may have these properties.”
MSDN still speaks of “layout properties,” but the meaning has changed, they are not associated with elements having layout anymore. In IE5.5, the property
hasLayout was introduced, more or less an internal flag.
In IE5.5, the documentation of the MSHTML Editing Platform (which allows for live editing, sizing, and dragging layout elements via
<body contenteditable=true>) reveals three important aspects related to having layout:
If a layout element has contents, the layout of its contents is determined by its bounding rectangle.
Having layout basically means an element is rectangular.
Internally, having layout means that an element is responsible for drawing its own content
Another possible related aspect is a change in the
With Internet Explorer 5.5 syntax, the Shadow, DropShadow, and Glow filters extend the boundary of an object to make room for the filter effect
(Filters and Transitions
That's all what we have found so far. The concept of layout itself is not documented.
Our interpretation is an attempt to explain what happens in known cases, and it should serve as a guide for cases not fully known. The attempt to demystify a black box only by inserting some test cases into it and listen if it rattles is doomed to failure. The “question why” cannot be answered. We have to try to understand the framework in which the whole “hasLayout” model works, and how it affects rendering of web documents. Out of this guidelines can be developed (and those can only be guidelines, not absolute solutions).
We think they speak of a little window. The content of a layout element would be completely independent from anything outside of the element's boundary, and the content couldn't affect anything outside either.
The hasLayout property is a sort of flag: when it is set, the element has this special layout “quality”, which includes special capabilities on the floating, clearing, stacking, counting and so on for the element itself and for its non-layouted child elements.
This greater independence of layout elements is probably the reason why they are usually more stable, and so they make some bugs to disappear. The price for this can be both deviance from standards, and further bugs/problems at their boundaries.
The MS “page” model, thinking in semiotics, can be seen as consisting of little blocks of stories that are unrelated, where as the HTML and W3C model has “page” model as complete narrative, story, blocks of information that are related.
A review of the consequences
Clearing floats and the extend to fit
Floats are auto-contained by layout elements. That's one reason why most beginners struggle with their IE-build pages in a compliant browser where floats stick out of the container when not cleared.
The opposite behavior: In IE, some fixes do apply layout to a container, but what if this container now (undesirably) contains floats with this fix? They don't stick out of the container anymore, we have to move them via
position: relative and
margin: negative value just to get the design back.
The known behavior to expand a container to fit any wider content can be seen as an aspect of the “determined by its bounding rectangle” rule.
clear can't affect a float outside of the clearer's layout container. Float layouts relying on that bug in IE cannot be transferred to work in a compliant browser without a general re-do.
A serious problem is that currently
overflow: hidden is used for a simple clearing of floats. When using this elegant method, hide
overflow: hidden from IE5.5 / quirksmode IE6. It has no effect on containing floats in IE-Win, and it's a potential risk: When the Holly hack is needed too for some other reasons, IE5.5 / quirksmode IE6 will respect that and will hide anything extending beyond 1%, and the cleared container will collapse. This is true if that cleared container is a direct child of
<body> or of a parent that relates its height to
Elements next to floats
When a block follows a left floating element, the text content should flow right to the float and slide under the float. But if the block has layout, say, a width is set for some reasons, the layout element behaves like a rectangle, the text does not slide under the float. The width is incorrectly calculated starting at the right of the float, so
width: 100% adds to the width of the float, resulting in a horizontal scrollbar. This is far off out of the specs.
Similar to this, actually, relatively positioned elements next to floats should offset with respect to the padding edge of the parent (i.e.
left: 0; on a r.p. element would place it on top of a preceding left floated box). In IE, the offset
left: value; starts from the right margin edge of the float, causing a horizontal misalignment by the total outer width of the float (a workaround is to use
margin-left instead, but beware the quirky percentages flaws).
According to the specs, floats interweave with subsequent boxes. This cannot be accomplished with two-dimensional rectangles which don't intersect.
By (re-)visiting this bug page
we'll see that the layout box following the float will not show the 3px text jog, because the float's hardwired 3px surrounding cannot affect the content inside the layout element anymore, but moves the whole layout element by 3px. Like a shield, layout prevented the content from been affected, but the energy of the push by the float moves the shielded box itself.
Go back one step, don't let the box gain layout. Imagine the float would have been applied a
DropShadow. This shadow leaves the boundary of the float, and adds to the 3px text jog!
Lists are affected by layout applied either to the list (
ol, ul) or to the list elements (
li.) Different versions of IE react differently. The most evident effects are on the list markers (fully customized lists where the markers are not required won't have these problems.) The markers are probably created by internally adding some elements that are somewhat “attached” to the list elements (usually hangs out of them) and seems rather unstable. Unfortunately, being “internal” only objects, they cannot be accessed to try to correct misbehaviours.
The most evident effects are:
- Layout applied to a list makes the markers to disappear or to be differently/wrongly positioned.
Sometimes they can be restored by changing margins on the list elements. This looks like a consequence of the fact that a layout element tends to crop internal elements hanging out of it.
A further problem is that (in ordered lists) any list element with layout seems to have its own counter. Let's say we have an ordered list with five elements where only the third has layout. We'll see this:
1... 2... 1... 4... 5...
Moreover when a list element with layout displays on multiple lines the marker is vertically aligned at the bottom (not at the top, as expected.)
Some of these problems cannot be cured, so when the markers are desired it's better to avoid layout on lists and list elements. If it's necessary to apply some dimension, this is better applied to other elements: for example a width can be applied to an external wrapper, and a height to the content of each list item.
Another common problem with lists in IE occurs when the content of any
li is an anchor with
display: block. In these conditions the white space between list items is not ignored and usually displayed as an extra line for each
li. One of the methods to avoid this extra vertical space is to give layout to the block anchors. This also has the benefit of making the whole rectangular area of the anchors clickable.
table always has layout, always behaves as a width defined object. In IE6,
table-layout: fixed is usually equivalent to a table with a width of 100%, with all problems that this brings (erroneous computations). As a side note, just a few things on the situation in IE5.5 and quirksmode IE6.
Relatively positioned elements
position: relative does not trigger hasLayout, which leads to some rendering errors, mostly disappearing or misplaced content. Inconsistencies might be encountered by page reload, window sizing and scrolling, selecting. With this property, IE offsets the element, but seems to forget to send a “redraw” to its layout child elements (as a layout element would have sent correctly in the signal chain of redraw events).
are related descriptions. As a rule of thumb, never position an element relatively without setting layout. In addition, we may check if the parent of such a construct needs layout and/or
position: relative too, this becomes essential when floats are affected.
Absolutely positioned elements: Containing block, what containing block?
It is essential to understand the CSS concept of the containing block, which answers where to relate an absolutely positioned (a.p.) element to: to define the offset origin, and to define the length percentages are calculated with respect to.
For a.p. elements, the containing block is established by its nearest positioned ancestor. If there is no such ancestor, the initial containing block of
html is used.
Normally, we would set such a containing block via position: relative. That means, we can let a.p. elements relate to lengths and origins independent from the flow of elements, i.e. to fulfill the needs of the “content first” accessibility concept or to make life easier in complex float layouts.
This design concept is questioned by IE, due to the concurring layout concept: the a.p. element is offset with respect to its nearest layout positioned ancestor, but the percentage dimension relates to the next layout ancestor. Note the slight difference, and as already mentioned, position: relative does not trigger hasLayout.
Say a non-layout parent is positioned relatively – we are urged to set layout to this parent to get the offset to work:
Say a non-positioned parent must have a dimension, and the design relies on a percentage width calculation – we can drop that idea, due to a lack of browser support:
filter is applicable to layout elements only. As mentioned above, some extend the boundary of an object. They show their own specific flaws.
Re-flow of rendered elements
Once all the elements are rendered, IE reflows the containing layout block when a :hover-transition (i.e., a change of the link's
background) is processed. Sometimes the elements are placed at a new position because at this moment the hover occurs, all the widths and offsets of the related elements are known to IE. This is unlike to the first round, where the width is undetermined yet due to the expand-to-fit feature. This can result in a jump on hover.
The relational bugs, based on the re-flow problem, query the use of percentages on margins and paddings in liquid layouts.
The hasLayout property affects the extension and the positioning of the
background. For example, according to the CSS spec,
background-position: 0 0 should refer to the “padding edge” of the element. In IE/Win it refers to
the “border edge” when
hasLayout=false, and to the “padding edge” when
hasLayout property affects the collapsing of margins between a box and
its descendants. According to the spec the top margin of a box with no top
padding and no top border should collapse with the top margin of its first
in-flow block-level child:
In IE/Win this never happens when the box has layout: it seems that layout prevents the margins of the children to stick out of the containing box. Moreover when
hasLayout is true, either on the container or on the child, other wrong margins computations show up:
hasLayout affects the clickable/hoverable area of a block-level anchor. Usually with hasLayout=false only the part covered by the text is sensitive. With hasLayout=true the whole block area is sensitive. The same is true for
any block element with an attached onclick/onmouseover event handler.
The stack, the layering, and layout
There seem to be two layering and stacking orders within IE/Win:
- One is the (pseudo) attempt to implement the css model: Effect of z-index value to RP and AP blocks
- Then there is the stacking order created by “hasLayout” and its twin the “contenteditable” behaviour. As shown in the example to relative positioning, not having layout can affect the stacking in a way Harry Houdini would had have fun with.
Both stacking models, though incompatible, are residents of IE's engine. As a rule of thumb: While debugging, don't miss checking both suspects. We regularly see related problems in drop down or similar complex menus, where the stacking, positioning and floating can lead to manifold disasters, and bugfixes may include giving z-indexed positioned layout, but it varies, so be warned.
contenteditable=true, set on a HTML tag like
<body contenteditable=true> allows for live editing, dragging and resizing the element and it's layout children. Now try that with floats or layout li in an ordered list.
In order to manipulate elements (edit them), “contenteditable” and
“hasLayout” introduce a separate stacking order for those elements which return
The Editing Platform inherits the layout-concept, evidence can be seen that contenteditable is the reason for the layout-misconception (with the implication that applications that somewhat integrate the IE editing engine force a backward compatibility to this layout-concept).
Are your MSIE-designed pages failing in other browsers? No need to let
that happen, you know! Any good browser can handle MSIE-designs just
fine if you ask them nicely - and serve them some valid CSS.
./. (under further investigation - more to come)
Some doctypes, or the inclusion of an
<xml> declaration, trigger quirksmode or backwards compatible mode in IE 6. In that case, IE 6 acts like IE 5.5, and shares the same bugs, problems and behaviour as its elder brother.
Layout – a conclusion
The layout concept as a whole is not compatible to a number of basic CSS concepts of the visual formatting model, namely containing, the flow, floating, positioning and layering.
This leads to IE/Win specific violations of the CSS specification due to the presence or absence of layout on elements in the page.
Having layout - part of another engine?
In conclusion, we see a lot of behavior ignoring the W3C CSS specs. Was the
contenteditable and the
filter worth all that specification violation?
The object model inside Explorer appears to be a hybrid of a document model and their traditional application model. I mention this as it is important in understanding how Explorer renders pages. The switch for jumping from a document model to an application model is to give an element “layout”
Sometimes it's impossible to give an interpretation to some behaviour: it's simply like, depending on hasLayout status, one of two different rendering engines is used, each one with its own quirks and bugs.
This article was created on June 30, 2005 and last changed on August 20, 2005.
- Holly Bergevin
- Ingo Chao
- Bruno Fassino
- John Gallant
- Georg Sørtun
- Philippe Wittenbergh
- Special thanks for supporting the project to:
- Dean Edwards
- Discuss this article:
- Contact us:
- Copyright notice:
- This work is published under a Creative Commons license.
Table of content