18.2 Element Positioning with CSS
For DHTML content developers, the most
important feature of CSS is the ability to use ordinary CSS
style
attributes to specify the visibility, size, and precise position of
individual elements of a document. In order to do DHTML programming,
it is important to understand how these style attributes work. They
are summarized in Table 18-2 and documented in more
detail in the sections that follow.
Attribute(s) | Description |
---|---|
position | Specifies the type of positioning applied to an element |
top, left | Specifies the position of the top and left edges of an element |
bottom, right | Specifies the position of the bottom and right edges of an element |
width, height | Specifies the size of an element |
z-index | Specifies the "stacking order" of an element relative to any overlapping elements; defines a third dimension of element positioning |
display | Specifies how and whether an element is displayed |
visibility | Specifies whether an element is visible |
clip | Defines a "clipping region" for an element; only portions of the element within this region are displayed |
overflow | Specifies what to do if an element is bigger than the space allotted for it |
18.2.1 The Key to DHTML: The position Attribute
The CSS position
attribute
specifies the type of positioning
applied to an element. The four possible values for this attribute
are:
static
This is the default value and specifies that the element is
positioned according to the normal flow of document content (for most
Western languages, this is left to right and top to bottom.)
Statically positioned elements are not DHTML elements and cannot be
positioned with the top, left,
and other attributes. To use DHTML positioning techniques with a
document element, you must first set its position
attribute to one of the other three values.
absolute
This value allows you to specify the position of an element relative
to its containing element. Absolutely positioned elements are
positioned independently of all other elements and are not part of
the flow of statically positioned elements. An absolutely positioned
element is positioned either relative to the
<body> of the document or, if it is nested
within another absolutely positioned element, relative to that
element. This is the most commonly used positioning type for DHTML.
fixed
This value allows you to specify an element's position with
respect to the browser window. Elements with fixed
positioning do not scroll with the rest of the document and thus can
be used to achieve frame-like effects. Like absolutely positioned
elements, fixed-position elements are independent of all others and
are not part of the document flow. Fixed positioning is a CSS2
feature and is not supported by fourth-generation browsers. (It is
supported in Netscape 6 and IE 5 for the Macintosh, but it is not
supported by IE 5 or IE 6 for Windows).
relative
When the position attribute is set to
relative, an element is laid out according to the
normal flow, and its position is then adjusted relative to its
position in the normal flow. The space allocated for the element in
the normal document flow remains allocated for it, and the elements
on either side of it do not close up to fill in that space, nor are
they "pushed away" from the new position of the element.
Relative positioning can be useful for some static graphic design
purposes, but it is not commonly used for DHTML effects.
18.2.2 Specifying the Position and Size of Elements
Once you have set the
position attribute of an element to something
other than static, you can specify the position of
that element with some combination of the
left , top,
right, and bottom attributes.
The most common positioning technique is to specify the
left and top attributes, which
specify the distance from the left edge of the containing element
(usually the document itself ) to the left edge of the element, and
the distance from the top edge of the container to the top edge of
the element. For example, to place an element 100 pixels from the
left and 100 pixels from the top of the document, you can specify CSS
styles in a style attribute as follows:
<div style="position: absolute; left: 100px; top: 100px;">
The containing element relative to which a dynamic element is
positioned is not necessarily the same as the containing element
within which the element is defined in the document source. Since
dynamic elements are not part of normal element flow, their positions
are not specified relative to the static container element within
which they are defined. Most dynamic elements are positioned relative
to the document (the <body> tag) itself. The
exception is dynamic elements that are defined within other dynamic
elements. In this case, the nested dynamic element is positioned
relative to its nearest dynamic ancestor.
Although it is most common to specify the position of the upper-left
corner of an element with left and
top, you can also use right and
bottom to specify the position of the bottom and
right edges of an element relative to the bottom and right edges of
the containing element. For example, to position an element so that
its bottom-right corner is at the bottom-right of the document
(assuming it is not nested within another dynamic element), use the
following styles:
position: absolute; right: 0px; bottom: 0px;
To position an element so that its top edge is 10 pixels from the top
of the window and its right edge is 10 pixels from the right of the
window, you can use these styles:
position: fixed; right: 10px; top: 10px;
Note that the right and bottom
attributes are newer additions to the CSS standard and are not
supported by fourth-generation browsers, as top
and left are.
In addition to the position of elements, CSS allows you to specify
their size. This is most commonly done by providing values for the
width and height style
attributes. For example, the following HTML creates an absolutely
positioned element with no content. Its width,
height, and background-color
attributes make it appear as a small blue square:
<div style="position: absolute; left: 10px; right: 10px;
width: 10px; height: 10px; background-color: blue">
</div>
Another way to specify the width of an element is to specify a value
for both the left and right
attributes. Similarly, you can specify the height of an element by
specifying both top and bottom.
If you specify a value for left,
right, and width, however, the
width attribute overrides the
right attribute; if the height of an element is
over-constrained, height takes priority over
bottom.
Bear in mind that it is not necessary to specify the size of every
dynamic element. Some elements, such as images, have an intrinsic
size. Furthermore, for dynamic elements that contain text or other
flowed content, it is often sufficient to specify the desired width
of the element and allow the height to be determined automatically by
the layout of the element's content.
In the previous positioning examples, values for the position and
size attributes were specified with the suffix "px". This
stands for
pixels. The CSS standard allows
measurements to be done in a number of other units, including inches
("in"), centimeters ("cm"), points
("pt"), and ems ("em" -- a measure of the
line height for the current font). Pixel units are most commonly used
with DHTML programming. Note that the CSS standard requires a unit to
be specified. Some browsers may assume pixels if you omit the unit
specification, but you should not rely on this behavior.
Instead of specifying absolute positions and sizes using the units
shown above, CSS also allows you to specify the position and size of
an element as a percentage of the size of the containing element. For
example, the following HTML creates an empty element with a black
border that is half as wide and half as high as the containing
element (or the browser window) and centered within that element:
<div style="position: absolute; left: 25%; top: 25%; width: 50%; height: 50%;
border: 2px solid black">
</div>
18.2.2.1 Element size and position details
It is important to understand some details about how the
left , right,
width, top,
bottom, and height attributes
work. First, width and height
specify the size of an element's content area only; they do not
include any additional space required for the element's
padding, border, or margins. To determine the full onscreen size of
an element with a border, you must add the left and right padding and
left and right border widths to the element width, and you must add
the top and bottom padding and top and bottom border widths to the
element's height.
Since width and height specify
the element content area only, you might think that
left and top (and
right and bottom) would be
measured relative to the content area of the containing element. In
fact, the CSS standard specifies that these values are measured
relative to the outside edge of the containing element's
padding (which is the same as the inside edge of the element's
border).
Let's consider an example to make this clearer. Suppose
you've created a dynamically positioned container element that
has 10 pixels of padding all the way around its content area and a 5
pixel border all the way around the padding. Now suppose you
dynamically position a child element inside this container. If you
set the left attribute of the child to "0
px", you'll discover that the child is positioned with
its left edge right up against the inner edge of the
container's border. With this setting, the child overlaps the
container's padding, which presumably was supposed to remain
empty (since that is the purpose of padding). If you want to position
the child element in the upper left corner of the container's
content area, you should set both the left and
top attributes to "10px". Figure 18-1 helps to clarify this.
Figure 18-1. Dynamically positioned container and child elements with some CSS attributes

Now that you understand that width and
height specify the size of an element's
content area only and that the left,
top, right, and
bottom attributes are measured relative to the
containing element's padding, there is one more detail you must
be aware of: Internet Explorer Versions 4 through 5.5 for Windows
(but not IE 5 for the Mac) implement the width and
height attributes incorrectly and include an
element's border and padding (but not its margins). For
example, if you set the width of an element to 100 pixels and place a
10-pixel margin and a 5-pixel border on the left and right, the
content area of the element ends up being only 70 pixels wide in
these buggy versions of Internet Explorer.
In IE 6, the CSS position and size
attributes work correctly when the browser is in standards mode and
incorrectly (but compatibly with earlier versions) when the browser
is in compatibility mode. Standards mode, and hence correct
implementation of the CSS "box model," is triggered by
the presence of a
<!DOCTYPE> tag at the start of the
document, declaring that the document adheres to the HTML 4.0 (or
later) standard or some version of the XHTML standards. For example,
any of the following three HTML document type declarations cause IE 6
to display documents in standards mode:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Strict//EN">
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
Netscape 6 and the Mozilla
browser handle the width and
height attributes correctly. But these browsers
also have standards and compatibility modes, just as IE does. The
absence of a <!DOCTYPE> declaration puts the
Netscape browser in quirks mode, in which it mimics certain
(relatively minor) nonstandard layout behaviors of Netscape 4. The
presence of <!DOCTYPE> causes the browser to
break compatibility with Netscape 4 and correctly implement the
standards.
18.2.3 The Third Dimension: z-index
We've seen that the
left, top,
right, and bottom attributes
can
be used to specify the X and Y coordinates of an element within the
two-dimensional plane of the containing element. The
z-index attribute defines a kind of third
dimension: it allows you to specify the stacking order of elements
and indicate which of two or more overlapping elements is drawn on
top of the others. The z-index attribute is an
integer. The default value is zero, but you may specify positive or
negative values (although fourth-generation browsers may not support
negative z-index values). When two or more
elements overlap, they are drawn in order from lowest to highest
z-index; the element with the highest
z-index appears on top of all the others. If
overlapping elements have the same z-index, they
are drawn in the order in which they appear in the document, so the
last overlapping element appears on top.
Note that z-index stacking applies only to sibling
elements (i.e., elements that are children of the same container). If
two elements that are not siblings overlap, setting their individual
z-index attributes does not allow you to specify
which one is on top. Instead, you must specify the
z-index attribute for the two sibling containers
of the two overlapping elements.
Nonpositioned elements are always laid out in a way that prevents
overlaps, so the z-index attribute does not apply
to them. Nevertheless, they have a default z-index
of zero, which means that positioned elements with a positive
z-index appear on top of the normal document flow,
and positioned elements with a negative z-index
appear beneath the normal document flow.
Note, finally, that some browsers do not honor the
z-index attribute when it is applied to
<iframe> tags, and you may find that inline
frames float on top of other elements, regardless of the specified
stacking order. You may have the same problem with other
"windowed" elements such as
<select> drop-down menus. Fourth-generation
browsers may display all form-control elements on top of absolutely
positioned elements, regardless of z-index
settings.
18.2.4 Element Display and Visibility
There are two CSS attributes you
can use to affect the visibility of a document
element: visibility and
display. The visibility
attribute is simple: when the attribute is set to the value
hidden, the element is not shown; when it is set
to the value visible, the element is shown. The
display attribute is more general and is used to
specify the type of display an item receives. It specifies whether an
element is a block element, an inline element, a list item, and so
on. When display is set to
none, however, the affected element is not
displayed, or even laid out, at all.
The difference between the visibility and
display style attributes has to do with their
effect on elements that are not dynamically positioned. For an
element that appears in the normal layout flow (with the
position attribute set to
static or relative), setting
visibility to none makes the
element invisible but reserves space for it in the document layout.
Such an element can be repeatedly hidden and shown without changing
the document layout. If an element's display
attribute is set to none, however, no space is
allocated for it in the document layout; elements on either side of
it close up as if it were not there. (visibility
and display have equivalent effects when used with
absolute- or fixed-position elements, since these elements are never
part of the document layout anyway.) You'll typically use the
visibility attribute when you are working with
dynamically positioned elements. The display
attribute is useful when creating things like expanding and
collapsing outlines.
Note that it doesn't make much sense to use
visibility or display to make
an element invisible unless you are going to use JavaScript to
dynamically set these attributes and make the element visible at some
point![3] You'll
see how you can do this later in the chapter.
[3] There is an exception: if you are creating a
document that depends on CSS, you can warn users of browsers that do
not support CSS with code like this:
18.2.5 Partial Visibility: overflow and clip
The visibility
attribute allows you to completely
hide a document element. The overflow and
clip attributes allow you to display only part of
an element. The overflow attribute specifies what
happens when the content of an element exceeds the size specified
(with the width and height
style attributes, for example) for the element. The allowed values
and their meanings for this attribute are as follows:
visible
Content may overflow and be drawn outside of the element's box
if necessary. This is the default.
hidden
Content that overflows is clipped and hidden so that no content is
ever drawn outside the region defined by the size and positioning
attributes.
scroll
The element's box has permanent horizontal and vertical
scrollbars. If the content exceeds the size of the box, the
scrollbars allow the user to scroll to view the extra content. This
value is honored only when the document is displayed on a computer
screen; when the document is printed on paper, for example,
scrollbars obviously do not make sense.
auto
Scrollbars are displayed only when content exceeds the
element's size, rather than being permanently displayed.
While the overflow property allows you to specify
what happens when an element's content is bigger than the
element's box, the clip property allows you
to specify exactly which portion of an element should be displayed,
whether or not the element overflows. This attribute is especially
useful for scripted DHTML effects in which an element is
progressively displayed or uncovered.
The value of the clip property specifies the
clipping region for the element. In CSS2 clipping regions are
rectangular, but the syntax of the clip attribute
leaves open the possibility that future versions of the standard will
support clipping shapes other than rectangles. The syntax of the
clip attribute is:
rect(top right bottom left)
The top, right,
bottom, and
left values specify the boundaries of the
clipping rectangle relative to the upper-left corner of the
element's box.[4] For example, to display only a
100 x 100-pixel portion of an element, you can give that
element this style attribute:
[4] As the CSS2 specification was
originally written, these four values specified the offset of the
edges of the clipping region from each of the corresponding edges of
the element's box. All major browser implementations got it
wrong, however, and interpreted the right
and bottom values as offsets from the left
and top edges. Because the implementations consistently disagree with
the specification, the specification is being modified to match the
implementations.
style="clip: rect(0px 100px 100px 0px);"
Note that the four values within the parentheses are length values
and must include a unit specification, such as "px" for
pixels. Percentages are not allowed. Values may be negative to
specify that the clipping region extends beyond the box specified for
the element. You may also use the keyword auto for
any of the four values to specify that that edge of the clipping
region is the same as the corresponding edge of the element's
box. For example, you can display just the leftmost 100 pixels of an
element with this style attribute:
style="clip: rect(auto 100px auto auto);"
Note that there are no commas between the values, and the edges of
the clipping region are specified in clockwise order from the top
edge.
18.2.6 CSS Positioning Example
Example 18-2 is a nontrivial
example using CSS style sheets and CSS positioning attributes. When
this HTML document is displayed in a CSS-compliant browser, it
creates the visual effect of "subwindows" within the
browser window. Figure 18-2 shows the effect created
by the code in Example 18-2. Although the listing
contains no JavaScript code, it is a useful demonstration of the
powerful effects that can be achieved with CSS in general and the CSS
positioning attributes in particular.
Figure 18-2. Windows created with CSS

Example 18-2. Displaying windows with CSS
<head>
<style type="text/css">
/**
* This is a CSS style sheet that defines three style rules that we use
* in the body of the document to create a "window" visual effect.
* The rules use positioning attributes to set the overall size of the window
* and the position of its components. Changing the size of the window
* requires careful changes to positioning attributes in all three rules.
**/
div.window { /* Specifies size and border of the window */
position: absolute; /* The position is specified elsewhere */
width: 300px; height: 200px; /* Window size, not including borders */
border: outset gray 3px; /* Note 3D "outset" border effect */
}
div.titlebar { /* Specifies position, size, and style of the titlebar */
position: absolute; /* It's a positioned element */
top: 0px; height: 18px; /* Titlebar is 18px + padding and borders */
width: 290px; /* 290 + 5px padding on left and right = 300 */
background-color: ActiveCaption; /* Use system titlebar color */
border-bottom: groove black 2px; /* Titlebar has border on bottom only */
padding: 3px 5px 2px 5px; /* Values clockwise: top, right, bottom, left */
font: caption; /* Use system font for titlebar */
}
div.content { /* Specifies size, position and scrolling for window content */
position: absolute; /* It's a positioned element */
top: 25px; /* 18px title+2px border+3px+2px padding */
height: 165px; /* 200px total - 25px titlebar - 10px padding */
width: 290px; /* 300px width - 10px of padding */
padding: 5px; /* Allow space on all four sides */
overflow: auto; /* Give us scrollbars if we need them */
background-color: #ffffff; /* White background by default */
}
</style>
</head>
<body>
<!-- Here is how we define a window: a "window" div with a titlebar and -->
<!-- content div nested between them. Note how position is specified with -->
<!-- a style attribute that augments the styles from the style sheet. -->
<div class="window" style="left: 10px; top: 10px; z-index: 10;">
<div class="titlebar">Test Window</div>
<div class="content">
1<br>2<br>3<br>4<br>5<br>6<br>7<br>8<br>9<br>0<br> <!-- Lots of lines to -->
1<br>2<br>3<br>4<br>5<br>6<br>7<br>8<br>9<br>0<br> <!-- demonstrate scrolling -->
</div>
</div>
<!-- Here's another window with different position, color, and font weight -->
<div class="window" style="left: 170px; top: 140px; z-index: 20;">
<div class="titlebar">Another Window</div>
<div class="content" style="background-color:#d0d0d0; font-weight:bold;">
This is another window. Its <tt>z-index</tt> puts it on top of the other one.
</div>
</div>
</body>
The major shortcoming of this example is that the style sheet
specifies a fixed size for all windows. Because the titlebar and
content portions of the window must be precisely positioned within
the overall window, changing the size of a window requires changing
the value of various positioning attributes in all three rules
defined by the style sheet. This is difficult to do in a static HTML
document, but it would not be so difficult if we could use a script
to set all of the necessary attributes. We'll explore this
topic in the next section.