[ Team LiB ] Previous Section Next Section

13.5 Adjusting Positioned Element Stacking Order (z-order)

NN 4, IE 4

13.5.1 Problem

You want to control the way an overlapping element appears in front of or behind another element.

13.5.2 Solution

You can either use the setZIndex( ) function from the DHTML library (Recipe 13.3) for backward-compatibility or, for all browsers that support the style property of elements, adjust the style.zIndex property directly:

document.getElementById("myLayer").style.zIndex = "100";

13.5.3 Discussion

Turning an element into a positioned element automatically raises it to a layer in front of the main document content. Unless the background of a layer is set to a color or image, the element's background is transparent by default, allowing content underneath to be visible in the blank spaces.

If the stacking order of a positioned element doesn't have to change during user interaction with the page, you can simply set the initial value via the CSS z-index property and be done with it. But there are times when scripts need to adjust the stacking order. For example, if you have multiple draggable elements on the page (see Recipe 13.11), you must ensure that the element being dragged is in front of all other elements, including other positioned elements. Otherwise the dragged item will submarine beneath other positioned elements and befuddle the user. Once dropped behind other items, the element may be lost.

Stacking rules are pretty simple. If any two elements have the same z-index value, the elements stack in source code order, with the element that comes later in the source code appearing in front of the earlier item. The default CSS z-index value for a positioned element is auto, which equates to zero. A negative value does not layer the element behind the main content. An element with a higher z-index value appears in front of elements with lower numbers. Thus, you can control the layering regardless of source code order.

In the drag scenario just mentioned (and demonstrated in Recipe 13.11), the script that responds to the mouse event signaling the activation of a draggable element should raise the zIndex property value of the dragged element to a number guaranteed to be higher than all others. There is no practical limit to the value you assign. Therefore, it's not uncommon to assign an arbitrarily high number, such as 100 or 1000, to an item that must be in front of all others. But once the user releases the dragged element, you need to restore the original value (which you should have preserved in a variable or custom property for later recall). This leaves room for the next dragged item to be assigned that high number so it appears in front of all others.

Beware, however, of mixing positioned elements and form controls. Except in the most recent browsers, you will encounter rendering conflicts between layers and several types of form controls when the layers are intended to overlap those controls. The most common offenders are text-based controls, such as text input elements, textarea elements, and select elements (which frequently use text-editing innards to display their content).

Unfortunately, when these conflicts arise, you can do nothing to make the layer display in front of the form control. Even the biggest number assigned to the zIndex style property won't help. If you cannot rework the design so that the overlap does not occur, the only workaround is to hide the form controls whenever the layer is visible. The best way to do this is to wrap the affected form in a relative-positioned span, and then change its style.visibility property as needed. This keeps the rest of the page from shifting around when the controls hide or show themselves.

13.5.4 See Also

Recipe 13.3 and its utility library for changing stacking order, among other DHTML tasks.

    [ Team LiB ] Previous Section Next Section