Making the Web Work for Community.
MahZeh Tools

Solutions to the IE z-index Bug: JavaScript
I have previously discussed the IE z-index bug and how CSS can, in some situations, be fudged to work around it. Here is a practical scenario in which that approach doesn’t work:
Each of these relative-positioned blocks contains an absolute-positioned block that is invisible until the user activates a script that displays it. (Click on the “Eat Me” and “Drink Me” links.)
The pop-up child blocks are each positioned to overlap both of the parent blocks. But where they overlap, the first (”Eat Me”) pop-up would appear underneath the second (”Drink Me”) parent block, which is after it in the document markup and therefore is drawn after. So I have assigned the pop-ups a z-index to make them stack on top of any other elements on the page. This works in Mozilla/Firefox and other standards-compliant browsers, but not in IE.
Because IE considers each of the relative-positioned parent blocks to establish its own independent z-index stack, assigning z-index for either of the pop-up child blocks has no effect on its stacking order with respect to any element outside of its parent block. We can set z-index on the parent blocks, but one will always end up stacking on top of the other (including its pop-up child), so it seems there is no solution in CSS.
This is not an academic problem. Pop-up context items are a worthy user interface aspiration, and the designer can’t (and shouldn’t have to) always guarantee that they will never overlap each other’s containing blocks. Because this scenario involves user interaction, however, and it isn’t unreasonable to expect that we only need one pop-up displayed at one time, it is possible to solve the problem with JavaScript.
Here is the solution:
var iaz_preserved_elements = [];
var iaz_preserved_zindexes = [];
function ie_apply_zindex(element_id, zindex, context_id) {
// default values
if (undefined == zindex) { zindex = 1; }
var context = (undefined == context_id ? $(context_id) : $(document.body));
var element = $(element_id);
// undo past ie_apply_zindex()
for (i = iaz_preserved_elements.length-1; i >= 0; i--) {
iaz_preserved_elements[i].setStyle({'z-index': iaz_preserved_zindexes[i]});
}
iaz_preserved_elements = [];
iaz_preserved_zindexes = [];
// find relative-positioned ancestors of element within context
element.ancestors().each(
function(ancestor) {
if ('relative' == ancestor.getStyle('position')) {
// preserve ancestor's current z-index
iaz_preserved_elements.push(ancestor);
iaz_preserved_zindexes.push( ancestor.getStyle('z-index') );
// apply z-index to ancestor
ancestor.setStyle({'z-index': zindex});
}
if (ancestor == context) { throw $break; }
}
);
}
The ie_apply_zindex function takes two parameters with an optional third:
- the ID of the z-indexed element
- the z-index value
- optionally, the ID of the block within whose context we’re concerned about this element getting its rightful z-indexed stacking order (defaults to the entire document)
Note that this script depends on the Prototype Framework and will not work without it. If you’re building an interactive UI that requires this kind of functionality, you really should be using a JavaScript library like Prototype, JQuery, or YUI to begin with.
Finally, here is the same example as above, with a call added to is_apply_zindex when the popup is displayed, in order to force it (by forcing its relative-positioned containing block — and all of that block’s containing blocks as well) to have the specified z-index, in IE, relative to any other element in the DOM. Now both of the pop-ups display correctly in IE.





April 11th, 2007 > MahZeh.org » Blog Archive » Solutions to the IE z-index Bug: CSS says:
[…] There is a special case of the z-index problem, involving pop-up items, that can only be solved with JavaScript. I have described the problem and the fix here. […]
June 5th, 2007 > boogdesign posts - Scriptaculous Draggable and Z-index says:
[…] creates a new stacking context (or at least, has an equivalent effect) in Firefox, whereas it seems IE’s broken z-index handling was what allowed me to end up with something which worked […]
July 6th, 2007 > Kevin says:
Thank you! Your explanation was lucid, your demonstration was very helpful, and your JavaScript approach was just the thing to salvage the little that’s left of my hair.