Cascading style sheets, as described in Chapter 3, are primarily concerned with how content looks on the screen (or how it looks on a page printed from the screen). An extension to CSS, called CSS-Positioning (or CSS-P), is primarily concerned with where content appears on the page. CSS-P is blended with regular CSS in the CSS2 specification, but because the Version 4 browsers were designed while positioning was a separate standards effort, I use the CSS-P term frequently.
The CSS-P recommendation from the W3C focuses on the HTML code that authors put into documents to govern the position of elements on the page when the browser-controlled flow of content just isn’t good enough. To accomplish element positioning, a browser must be able to treat positionable elements as layers[2] that can be dropped anywhere on the page, even overlapping other fixed or positionable elements—something that normal HTML rendering scrupulously avoids.
The notion of layering adds a third dimension to a page, even if a video monitor (or a printed page) is undoubtedly a two-dimensional realm. That third dimension—the layering of elements—is of concern to you as the author of positionable content, but is probably of no concern to the page’s human viewer.
While the CSS-P recommendation offers a cross-platform way to lay out positionable elements, the browsers have extended the idea by turning positionable elements into scriptable objects whose properties can be changed in response to user action. Now you have the opportunity to create some very interactive content: content that flies around the page, hides and shows itself at will, centers itself horizontally and vertically in the currently sized browser window, and even lets itself be dragged around the page by the user.
The implementations of positionable elements in Navigator 4 and Internet Explorer 4 are perhaps the most divergent parts of DHTML to grace both browsers. If you have the luxury of designing an application for only one browser platform, you can focus on the implementation for that browser to the exclusion of the other browser’s idiosyncrasies. Successful cross-platform development, however, requires knowledge of both browsers’ object models (at least as they relate to positionable elements) and the range of DHTML authoring capabilities in both browsers. As you will see in this chapter, there is a common denominator of functionality, but it is often up to you to raise the level of commonality in order to get a highly interactive page to work identically in both browsers.
Regardless of browser, you can make any
HTML container element (an element with a start and end tag) a
positionable element. As a ridiculous example of how true the
preceding statement is, you could direct a browser to render a word
surrounded by
<B>
/</B>
tags at a
position that is 236 pixels below its normal place in a paragraph
(but why would you?).
To
turn an HTML element into a positionable element that works in both
Navigator 4 and Internet Explorer 4, you must assign it a CSS style
rule that has a special attribute:
position
. As demonstrated in Chapter 3, you can assign this style attribute by
including a STYLE
attribute in the actual HTML tag
or using an ID selector for the rule and setting the corresponding
ID
attribute in the element’s HTML tag.
The following HTML document demonstrates the two techniques you can use to turn an element into a positionable element:
<HTML> <HEAD> <STYLE TYPE="text/css"> #someSpan {position:absolute; left:10; top:30} </STYLE> </HEAD> <BODY> <DIV ID="someDiv" STYLE="position:absolute; left:100; top:50"> Hello. <SPAN ID="someSpan"> Hello, again. </SPAN> </DIV> </BODY> </HTML>
The first technique defines an ID selector inside a
<STYLE>
tag that is mated to an
ID
attribute of a SPAN
element
in the document’s body. The second method defines the style as
an inline attribute of a <DIV>
tag. As with
ordinary CSS style sheets, you can use any combination of
methodologies to apply position style rules to elements in a
document.
Once you have set the position
attribute, you can
set other CSS-P attributes, such as left
and
top
, to position the element. Possible values for
the position
attribute are:
-
absolute
Element becomes a block element and is positionable relative to the element’s positioning context.
-
relative
Element maintains its normal position in element geography (unless you override it) and establishes a positioning context for nested items.
-
static
Item is not positionable and maintains its normal position in element geography (default value) .
The position
attribute terminology can be confusing because the coordinate system
used to place an element depends on the positioning context
of the element, rather than on a
universally absolute or relative coordinate system. A positioning
context defines a point somewhere on the screen that is coordinate
point 0,0. The most basic positioning context is the invisible box
created by virtue of the <HTML>
tag set of
the document, corresponding to the BODY
element.
In other words, the entire (scrollable, if necessary) space of the
browser window or frame that displays the content of the document is
the default positioning context. The 0,0 coordinate point for the
default positioning context is the upper left corner of the window or
frame. You can position an element within this context by setting the
position attribute to absolute
and assigning
values to the left
and top
attributes of the style rule:
<DIV ID="someDiv" STYLE="position:absolute; left:50; top:100"> Hello. And now it's time to say goodbye. </DIV>
Figure 4.1 shows how this simple block-level element appears in a browser window.
Each time an element is positioned, it spawns a new positioning
context with the 0,0 position located at the top left corner of that
element. Therefore, if we insert a positioned element in the previous
example nested within the DIV
element that forms
the new positioning context, the newly inserted element lives in the
new context. In the following example, we insert a
SPAN
element inside the DIV
element. Positioning attributes for the SPAN
element place it 10 pixels in from the left and 30 pixels down from
the top of its positioning context—the DIV
element in this case:
<DIV ID="someDiv" STYLE="position:absolute; left:100; top:50"> Hello. <SPAN ID="someSpan" STYLE="position:absolute; left:10; top:30"> Hello, again. </SPAN> And now it's time to say goodbye. </DIV>
Figure 4.2 shows the results; note how the
DIV
element’s positioning context governs
the SPAN
element’s location on the page.
Notice in the code listing that the position
attribute for each element is absolute
, even
though you might say that the nested SPAN
element
is positioned relative to its parent element. Now you see why the
terminology gets confusing. The absolute positioning of the
SPAN
element removes that element from the
document’s content flow entirely. The split content of the
parent DIV
element closes up, as if the content of
the SPAN
element wasn’t there. But the
SPAN
element is in the document—in its own
plane and shifted into a position within the DIV
element’s positioning context. All other parent-child
relationships of the DIV
and
SPAN
elements remain intact (style sheet rule
inheritance, for instance), but physically on the page, the two
elements appear to be disconnected.
The true meaning of relative positioning can be difficult to visualize because experiments with the combination of absolute and relative positioning often yield bewildering results. Whereas an absolute-positioned element adopts the positioning context of its HTML element parent, a relative-positioned element adopts the positioning context of the element’s normal (unpositioned) location within the document’s content flow. A sequence of modifications to some content should help demonstrate these concepts.
To begin, here is a fragment with a single absolute-positioned
DIV
element that contains three sentences:
<DIV ID="someDiv" STYLE="position:absolute; left:100; top:50"> Hello. Hello, again. And now it's time to say goodbye. </DIV>
This code generates a simple line of text on the page, as shown in Figure 4.3.
Pay special attention to the location of the middle sentence as it
flows in normal HTML. Now, if that second sentence is made into a
relative-positioned SPAN
element supplied with
some offset (left and top) values, something quite unusual happens on
the screen. The following fragment positions the second sentence 10
pixels in from the left and 30 pixels down from the top of some
positioning context:
<DIV ID="someDiv" STYLE="position:absolute; left:100; top:50"> Hello. <SPAN ID="someSpan" STYLE="position:relative; left:10; top:30"> Hello, again. </SPAN> And now it's time to say goodbye. </DIV>
But what is that context? With a relative-positioned element, the
anchor point of its positioning context is the top left corner of the
place (the box) where the normal flow of the content would go.
Therefore, by setting the left
and
top
attributes of a relative-positioned element,
as in the previous code fragment, you instruct the browser to offset
the content relative to its normal location. You can see the results
in Figure 4.4.
Note how the middle sentence is shifted within the context of its
normal flow location. The positioning context established by the
relative-positioned element is now available for positioning of other
elements (most likely as absolute-positioned elements) that you may
wish to insert within the <SPAN>
tag pair.
Take special notice in Figure 4.4 that the browser
does not close up the space normally occupied by the
SPAN
element’s content because it is a
relative-positioned element; had it been absolute-positioned, the
surrounding text would have closed the gap. All this behavior is
dictated by the CSS-P recommendation.
In most cases, you don’t assign values for
left
and top
to a
relative-positioned element because you want to use a
relative-positioned element to create a positioning context for more
deeply nested elements that are absolutely positioned within that
context. Using this technique, regular content flows according to the
browser window’s current size or as its appearance is affected
by style rules, while elements that must be positioned relative to
some running content are always positioned properly.
To demonstrate this concept, consider the following fragment that
produces a long string of one-word sentences. The goal is to have the
final sentence always appear aligned with the final period of the
last “Hello” and 20 pixels down. This means that the
final sentence needs to be positioned within a context created for
the final period of the last “Hello.” In other words, the
period character must be defined as a relative-positioned element, so
that the nested SPAN
element can be positioned
absolutely with respect to the period. The following code shows how
it’s done:
<DIV ID="someDiv" STYLE="position:absolute; left:100; top:50">Hello. Hello. Hello. Hello. Hello. Hello. Hello. Hello. Hello. Hello. Hello. Hello. Hello. Hello. Hello. Hello<SPAN ID="someSpan" STYLE="position:relative">. <SPAN ID="anotherSpan" STYLE="position:absolute; top:20"> And now it's time to say goodbye. </SPAN> </SPAN> </DIV>
Carefully observe the nesting of the elements in the previous example. Figure 4.5 shows the results in a small browser window.
If you resize the browser window so that the final “Hello” appears on another line or in another vertical position on the page, the final sentence moves so that it always starts 20 pixels and just to the right of the period of the final “Hello” of the content. When applied in this fashion, the term “relative positioning” makes perfect sense.
One of the advantages of CSS-Positioning is that you can set an absolute position for any element along both the horizontal and vertical axes as well as its position in stacking order—the third dimension. This makes it possible for more than one element to occupy the same pixel on the page, if you so desire. It is also important to remember that absolute-positioned elements exist independently of the surrounding content of the document. In other words, if a script shifts the position of such an element, the surrounding content does not automatically wrap itself around the new position of the element.
If your design calls for the content of an element to wrap around
another element, you should use the CSS
float
attribute, rather than CSS-Positioning.
Properties of the float
attribute let you affix an
element at the left or right margin of a containing block element and
at a specific location within the running content. For example, if
you want to place an image in the middle of a paragraph, you wrap
that image element inside a SPAN
element whose
style sets the float
attribute, as follows:
<P>Lots of text. <SPAN STYLE="float:right; width:120"> <IMG SRC="myImg.gif" HEIGHT=90 WIDTH=120> </SPAN> And more text.</P>
Now, no matter how the browser window is sized or how the font rendering varies from platform to platform, the text in the paragraph always wraps around the image. A floating element defined in this manner, however, is not a positionable element in that you cannot script positionable element properties of such an item.
Netscape Navigator 4 provides an alternate syntax for creating
positionable elements in the form of two sets of tags that are not
recognized by IE 4 or HTML 4.0. They are the
<LAYER>
and
<ILAYER>
tags, which correspond to absolute
and relative positioning styles, respectively. The basic concepts of
absolute and relative positioning from CSS-P apply to these tags, so
the discussion earlier in this chapter about the two positioning
styles applies equally well to Netscape layers. Because you use HTML
tags to generate these elements, attributes are set like regular HTML
attributes (attributeName="value"
), rather
than with the CSS-style rule syntax
(attributeName:value
).
The <LAYER>
tag generates an element that
can be absolute-positioned within the positioning context of the next
outer layer (or the base document if that’s the next outer
layer). The following code fragment from the body of a document
generates the same content shown earlier in Figure 4.2:
<LAYER NAME="someLayer" LEFT=100 TOP=50> Hello. <LAYER NAME="anotherLayer" LEFT=10 TOP=30> Hello, again. </LAYER> And now it's time to say goodbye. </LAYER>
The inner layer (anotherLayer
) is
absolute-positioned relative to the next outer layer
(someLayer
). That outer layer is
absolute-positioned relative to the default positioning context of
the document.
In the following fragment, the inner layer is changed to be a
relative-positioned element by using the
<ILAYER>
tag (inline layer):
<LAYER NAME="someLayer" LEFT=100 TOP=50> Hello. <ILAYER NAME="inLineLayer" LEFT=10 TOP=30> Hello, again. </ILAYER> And now it's time to say goodbye. </LAYER>
The
<ILAYER>
tag lets you designate a piece of
running content that has its own positioning context. In this case,
the <ILAYER>
content is positioned within
that context, leaving a gap in the running content, as shown earlier
in Figure 4.4.
A more practical application of the <ILAYER>
tag is to use it to set a positioning context for further nested
absolute-positioned layers. Thus, in the following code fragment, an
<ILAYER>
is applied to the final period of
the outer layer. The <LAYER>
tag nested
inside the <ILAYER>
tag obeys the
positioning context of that inline layer, such that the final content
tracks the location of the period regardless of normal content
wrapping, as shown earlier in Figure 4.5:
<LAYER ID="someLayer" LEFT=100 TOP=50>Hello. Hello. Hello. Hello. Hello. Hello. Hello. Hello. Hello. Hello. Hello. Hello. Hello. Hello. Hello. Hello<ILAYER NAME="inLineLayer">. <LAYER NAME="anotherLayer" TOP=20> And now it's time to say goodbye. </LAYER> </ILAYER> </LAYER>
There is more to the Netscape layer than its simply being an
alternative syntax to CSS-Positioning. Each layer
and inline layer
object can have external content
associated with it (via an SRC
attribute, as
documented in Chapter 8). In fact, in the document
object model for Navigator 4, each layer
object
contains its own document
object, which a script
can manipulate like any document
object. This
object model is vastly different from the one Internet Explorer 4
uses for positionable objects, so when it comes to writing scripts
that reference positionable objects, the situation gets a bit gnarly,
as described later.
One other point about the relationship between Netscape layers and CSS-P objects is that Navigator automatically converts CSS-P objects into layers for the object model of the currently loaded document. For example, the following document defines one positionable element in CSS-P syntax:
<HTML> <HEAD> </HEAD> <BODY> <DIV STYLE="position:absolute; left:100; top:50"> Hello. </DIV> </BODY> </HTML>
Navigator 4’s object model treats the DIV
element as a layer; “Hello.” is the content of the
layer’s document
object. Therefore, while
Navigator’s scripting environment works only with
layer
objects for controlling positioning, you
have the same level of scriptability whether a positionable element
is defined as a Navigator layer or as a CSS-P
element.
[2] I use the term “layer” guardedly here. While the
word appears in the Netscape DHTML lexicon (Navigator has a
<LAYER>
tag and a scriptable
layer
object), you probably won’t see the
same word being used by the Microsoft camp. My application of the
term is generic and it aptly describes what’s going on here: a
positionable element is like an acetate layer of a film cartoon cel.
The cartoon artist starts with a base layer for the scene’s
backdrop and then positions one or more acetate layers atop the
background; each layer is transparent except for some or all of the
art for a single frame of the film. For the next frame of the
cartoon, perhaps one of the layers for a character in the background
must move a fraction of an inch. The artist repositions that layer,
while the others stay the same. That’s what I mean by
“layer” in this context.
Get Dynamic HTML: The Definitive Reference now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.