hasLayout.net

IE hasLayout

Introduction

This article is a summary about hasLayout articles already publicly available.

Update: hasLayout has been removed from IE8 standards mode. It is still present in the IE7-compatibility mode.

Why hasLayout?

Fumle.dk -- site seems to have changed the owner (and possibly content)

MSIE has quite dated rendering engine (not surprising, as IE is based on Mosaic). In old tabular times, almost any element (except inline content) was a box. There was no way for content to leak from containing table cell, or for table cell to leak out of table...

Many years have passed, and Microsoft began adapting archaic Trident engine to make use of CSS. However, CSS changes the fundamental assumption that old engine was based on - the one that "anything significant" is a rectangle that contains all its content. CSS allows content to overflow out of container. This may happen when content is floated, or if content is too tall/wide to fit inside constrained box.

Where Did It Come From?

Microsoft's "genius" coders decided to fix their ancient engine in a rather bizarre way. And that is where the hasLayout "property" comes from. Every element has hasLayout set to either true or false. If it is set to true - element is a box that is responsible for rendering itself. Therefore, element would be expanded to contain overflowing content, such as floats or very_very_long_words_without_any_breaks. If hasLayout is set to false - element does not render itself, and instead hopes that some ancestor with hasLayout set will do the job for it. This is where the majority of IE bugs come to life.

The hasLayout "property" is not a CSS property, you can not set it with {hasLayout: true;} it would be too easy. An element with hasLayout set to true is often referred to as having layout, and hasLayout of false is referred to as not having layout.

Alright, Be Honest, Which One of You Has Layout?

The following elements have "layout" by default.

  • <html>, <body>
  • <table>, <tr>, <th>, <td>
  • <iframe>, <embed> (non-standard element), <object>, <applet>
  • <img>
  • <hr>
  • <input>, <button>, <select>, <textarea>, <fieldset>, <legend>
  • <marquee> (don't ever use this one, non-standard and annoying)

This list may be incomplete. Many of these elements are not even mentioned in Microsoft's documentation. However, it is very easy to test whether or not an element has "layout" or not. For example, consider the following code:

<div id="menu">
    ...
</div>

To determine "hasLayout" value for that <div> we could run this code in the location bar:

javascript:alert(menu.currentStyle.hasLayout)

After running the code above a message box should appear saying true or false which would represent the hasLayout value of the element with an ID attribute set to menu. If you get undefined it could mean that you specified a wrong ID, check your spelling.

Give Me Layout! Please!

Setting hasLayout to true, or in other words giving layout, is relatively easy as opposed to setting it to false.

The following properties/values give an element layout:

  • width: any value other than auto
  • height: any value other than auto

As of IE version 7, few new properties give "layout":

  • min-width: any value other than auto
  • max-width: any value other than auto
  • min-height: any value other than auto
  • max-height: any value other than auto

Microsoft finally got rid of hasLayout in IE8 standards mode, even though it is still present in IE7-compatibility mode (for obvious reasons).

You may be not familiar with zoom and writing-mode properties. Both are Microsoft's proprietary extensions. They work only in IE and will not validate. Therefore, I strongly advise you to put those into condcoms. However, writing-mode property is already in the CSS3 Technical Report, zoom property may make it there one day, but to my current knowledge it hasn't yet.

Zoom obviously zooms an element. For example, zoom: 2 will render the element twice its size, whereas zoom: 1 will render the element with normal dimensions, and that is why I personally think this is the best property to use inside conditional comments for giving an element "layout" since it has no other effects on the element.

Writing-mode property is a proposed addition to CSS3 that determines how the text should be written. The tb-rl value stands for "top to bottom, right to left", a typography style used in East Asia. Western typography is depicted "left to right, top to bottom", which would be lr-tb value for writing-mode property.

Setting display: inline-block and then reverting it back to the original display property value inside another rule set does not remove layout, this trick can be used to give layout without the use of conditional comments when you cannot use other properties. Here is how this trick would look like:

div { display: inline-block; }
div { display: block; } /* two separate rule sets */

Properties overflow-x and overflow-y have also made it into CSS3 Technical Report, thus still might not be well supported at the moment.

Setting proprietary contenteditable attribute also gives an element "layout".

<p contenteditable="true">so lame</p>

You should never use this one for setting hasLayout, it is shown here only for informational purposes. Not only contenteditable is a proprietary MS attribute (thus it will not validate) but also allows the user to edit the content of the element, which in best case will confuse the user.

The hasLayout "property" is read-only, you cannot set it directly with JavaScript for example.

I Don't Want It Anymore!

All sounds good until you come across a bug caused by hasLayout set to true. Since hasLayout is read-only, there is no way to set it to false other than not using properties/values that set it to true. Exception to this rule is display: inline-block, setting it to another value does not set hasLayout to false.

You cannot set hasLayout to false on elements that have "layout" by default. Luckly, most bugs in IE are caused by element not having layout.

Bugs All Around

With my experience I can say that around eighty percent of IE bugs are caused by an element not having "layout".

Bugs that are caused by the element having layout are not that common to come around. One of them can be seen here:

This is not one line

In IE this text will be shown in one line. It seems that the cause of this bug is that the <p> with hasLayout set to true does not properly inherit the white-space property from the parent element. Setting white-space: pre on the <p> itself or making sure it does not have "layout" fixes the bug.

IE hasLayout bugs are often present themselves with the most bizarre issues. If IE does something that you are having problems to explain with words - the first thing to try would be to give an element "layout".