When a typical HTML page loads, the browser flows the content according to its interpretation of how each element should appear on the page. Some elements have attributes that control various dimensions, either in terms of pixels or percentages of the available space, but again, the designer is at the mercy of the rendering engine of the browser. The tradition of HTML as a passive publishing medium is much cruder than print publishing, where the designer is in total control of every millimeter of space on the page.
Precise HTML content layout is often left up to twisting HTML tables and transparent images inside table cells to make sure the position relationships, say, between an image and its caption, meet the designer's expectations. In fact, if you play with WYSIWYG (What You See is What You Get) web page layout programs the same way you use print publishing layout tools (such as PageMaker or QuarkXpress), a mass of HTML table-related code frequently accrues behind the pretty page. Manually tweaking that gnarled code can sometimes lead to tears.
To fill the gap by providing publishing-quality control over content appearance, the style sheet concept has gained a strong footing in web publishing, particularly with the W3C-sponsored Cascading Style Sheets (CSS) recommendation. Not only is the raw content—the words and images, primarily—separated from the specifications of how the content is rendered, but the publishing world has contributed to mapping out the nature and breadth of CSS properties that can be applied to content.
Not long after the first release of a CSS recommendation, a supplementary standard appeared, covering the notion of positioning HTML content. As of CSS Level 2, element positioning became part of the main CSS recommendation. At its root, CSS positioning lets you specify the exact coordinates of an element within the document space. A positioned element exists in its own plane above the page, much like the acetate sheet that cartoon animators once used to create characters that moved (in succeeding acetate cels) in front of a fixed background. Before CSS positioning, each rendered HTML element occupied its own rectangular space on the page. With CSS positioning, you may overlap elements, which means that stacking order is also controllable. And since each positioned element lives in its own plane, positioned elements may also hide themselves and reappear without disturbing other element layout.
When you add the scripting capabilities of modern browsers to element positioning concepts, you open up a door to a wide array of user interface possibilities—page features that extend far beyond the web's original publishing concepts. Scripts can make an element jump from one position to another or glide slowly along a path (albeit not with the same level of speed control as is possible in dedicated animation technologies, such as Macromedia Flash). Interaction with mouse events allows scripts to track the location of an element along with the position of the mouse cursor on the screen for actual element dragging on the page. Another kind of positioning animation lets you create blocks of body text that automatically scroll for page visitors.
13.0.1 Positioning Scope
As you determine how you might wish to employ element positioning on your page, you have to consider the range of options you have with regard to the positioning context you wish to use. The most common positioning context is that of the entire space occupied by the web page inside the browser window. In this scenario, treat the area occupied by the page's content as your canvas, within which you can define the location of one or more elements, each residing in its own plane. This space has a two-dimensional coordinate system, with point 0,0 being the very top left of the page (the top-left corner of the browser's content region if the page is scrolled all the way to the top and left). Numbers for the coordinates increase as you move to the right and downward.
Another positioning context can be an already positioned element. In other words, you can position an element inside another positioned element. In this case, the more nested element uses the canvas of the outer element as its context. The outer element presents its own coordinate system, with point 0,0 being the top-left corner of the element. If the outer element is moved, the inner nested element moves right along with it, maintaining its interior coordinates relative to its positioning context.
An important design consideration to keep in mind is that even though a positioned element seems to float in front of all other content, it does not act like a browser window. If you position an element so that some of its area extends beyond the visible area of a web page, the positioned element is clipped to the edge of the window, rather than overlapping the browser's scrollbars or other window chrome. In fact, positioning an element outside of the regular document flow is likely to force the browser to resize the page, extending it in such a way as to display browser scrollbars where none existed before. This kind of clipping, however, does not occur when you position an element within another positioned element, unless you explicitly set the clipping rectangle of the outer container.
13.0.2 Positioning Types
You have a few positioning types to choose from. A helpful type, which is not implemented in IE for Windows through Version 6, is fixed positioning. This style allows an element to remain in a constant location in the content region of the browser window, regardless of page scrolling. Typical applications for a fixed element include floating control panels and page watermarks (similar to the network symbols that occupy the corners of many television channel screens). More common are two other types, whose names do not always convey their meaning: absolute positioning and relative positioning. Keeping the characteristics of these two types straight is important.
An absolute-positioned element is removed from the rest of the page's rendering flow, regardless of its location within the source code. A nonnested, absolute-positioned element uses the page coordinate space as its positioning context (more about this in a moment, because it's not exactly that simple). Any other HTML in the source code flows on the page as if the positioned element were not there. In fact, if you instruct an element to be positioned but fail to give it coordinates to follow, the positioned element appears at the top-left corner of the page, on top of whatever other content happens to be in that location. And yet, the element containment hierarchy with respect to nodes and their children in the document's object model still exists.
In contrast to the absolute-positioned element is the relative-positioned element. A significant difference between absolute- and relative-positioned elements is that a relative-positioned element influences the rendering flow of the main document content. The positioning context of a relative-positioned element is the location in the main document where the element normally appears if it is not positioned. In fact, if you specify an element as being relative-positioned and don't supply any coordinates (defaulting to 0,0), the element looks no different than if it were a non-positioned element. The difference, however, comes when you assign coordinates to the element. It moves (relative to its original position), and the surrounding content does not cinch up around the unused space.
A valuable application of a relative-positioned element is to provide a positioning context for some other absolute-positioned element. This lets the relative-positioned element to allow itself to flow into the page as normal (influenced by the browser window size, style sheet settings, and the like). But then a nested absolute-positioned element can define its location relative to that positioning context, such as 20 pixels below the end of a paragraph whose final period is a relative-positioned span element (see Recipe 13.2).
13.0.3 Evolving Contexts
In the first versions of Internet Explorer for Windows that permitted element positioning, Microsoft designed parts of their system in a way that ultimately was not adopted by the W3C in its CSS recommendation. To get back on the standards track, IE 6 implemented CSS more in line with the standard. But some of these changes could make older content—which looked and operated fine in IE 4 through 5.5—render in unexpected ways.
To bridge the gap, IE 6 includes two modes, one for backward compatibility and one for CSS compatibility. By default, IE 6 operates in backward-compatibility mode. But to switch it into CSS-compatibility mode, you need to define a DOCTYPE element at the top of the document with certain characteristics. Netscape 6 and later similarly has two modes, although the differences between the two are less apparent for typical positioning tasks. See Recipe 11.13 for details about defining an appropriate DOCTYPE element.
One important difference between the two modes in IE 6 is that the primary positioning context for an unnested element moves outward from the body element (as in IE 4 through 5.5) to the html element, which represents the full rendered document context. The difference is more than just symbolic because the body element in IE has some built-in margins that can affect precise positioning when trying to align positioned and non-positioned elements (see Recipe 13.6).
13.0.4 Incompatibility Hazards
Although less of an issue than it once was, you need to be aware of potential problems with older and underpowered browsers when you include positioned elements in the page. If a browser doesn't support the CSS positioning properties, the elements you have set aside as positioned elements render on the page in their source code order. Not only will your carefully positioned elements not be where you want them to be, they will likely confuse the visitor.
Counteracting this problem results in a variety of compromises, depending on your solution. One choice is to limit page access to browsers that support CSS positioning (IE 4 or later, Navigator 4 to some degree, Netscape 6 or later, Opera 5 or later, and any other browser that has a document.body.style object).
Another possibility is to use scripts to generate the HTML for positioned content dynamically while the page loads. The script can verify that the browser supports CSS, and then use document.write( ) to create the HTML. Of course, your page must be able to stand on its own without the positioned content to be meaningful to users of other older browsers. A potential downside to this technique is that search engines will not detect any links in the dynamically-generated content.
13.0.5 Units of Measure
Designers from the publishing world are accustomed to laying out content in a variety of units of measure, such as inches, centimeters, picas, points, and ems. CSS supports all of these units of measure for length values, but for the most part, they are difficult to work with in a medium that most commonly outputs to a video screen. In computer monitors, the pixel is king. It is also indivisible, so that any measure that attempts to split hairs in units other than pixels is likely doomed to failure.
Even if you intend the output to go to a printer, you may not get the results you expect if you specify units other than pixels. Browsers perform a lot of estimations, conversions, and interpolations between the screen-rendered output and what they send to a printer. It's true that you might get lucky with a design template in other units on a particular browser, but such results are the exception rather than the rule.
13.0.6 The Erstwhile <layer> Tag
Navigator 4 was the first browser to implement the notion of positioned elements, which it did via a new element called the layer. This effort pre-dated the W3C's effort to codify CSS positioning. When the standards body finished its work, it decided to steer clear of the <layer> tag and all associated coding. The Navigator 4 browser was a popular version, and developers created a lot of content that not only used the proprietary <layer> tag, but also the required Navigator 4 DOM syntax for referencing such elements to adjust their properties (e.g., to move or hide an element). In the meantime, Microsoft came up with its own referencing scheme, whereby any element (positioned or otherwise) could be referenced through the document.all collection. Equalizing references to the positioned-element properties of IE and NN 4 browsers was a part of any DHTML page at the time.
With the layer element eliminated from the standardized HTML grammar before it ever got there, developers of the next generation of Netscape browser made the difficult but ultimately correct decision to drop support for the <layer> tag and DOM reference scheme from the Mozilla browser (for Netscape 6 and later). Lots of Netscape-specific scripts broke during the transition, but thanks to the W3C DOM and support for it in current browsers, it is now possible to use the same HTML- and DOM-referencing syntax to produce and manipulate positioned elements on a wide range of browsers, including IE 5 or later. The W3C syntax is a stable development platform going forward.
One legacy of the Navigator 4 effort, however, is that positioned elements are frequently called layers, regardless of the browser platform. It is a convenient metaphor for the way these positionable, floating elements behave, and you will find this usage in this book as well.