Friday, August 7, 2009

CSS Positioning - 1

Web design usually means something more than just fonts, colours and
graphical elements. It also implies some sort of layout. A web designer has
three available tools for creating a layout:



* tables,

* floats,

* positioning.



Layout tables belong in the last millennium. Floats are often the best
solution, especially when you don't know in advance which column will be the
longest. Older browsers, and Internet Explorer, aren't too good at dealing with
floats, though. Besides, that's a separate topic.


Positioning is perhaps one of the most misunderstood parts of
CSS 2. Let us look a little
closer at how it works.



Absolute positioning is sometimes referred to as CSS-P.
Beginners using Dreamweaver tend to call it layers, which is
unfortunate, because it can be confused with Netscape's proprietary
element.


But let's start from the beginning. The position
property in CSS accepts four different values (plus
inherit):



* static,

* relative,

* absolute,

* fixed.



For all values except static we can affect the element's
position through the top, bottom, left
and right properties.


Static Positioning

Elements with position:static, which is the default value for
all elements, are not positioned at all. Their placement on the canvas is
determined by where they occur in the document.


Thus the static value is only used for overriding a
previously set value.


We will use the term "statically positioned" in this article, even
though it isn't fully correct.


Relative Positioning

Elements with position:relative are positioned relative to
themselves. This may sound strange, but it can be useful sometimes.


If we specify a value for either of the four edge properties, the relatively
positioned element is shifted in relation to the position it would have occupied
if it had been statically positioned.


This may sound like Greek to you, but it's actually quite logical. If we just
set position:relative on an element, without specifying any of the
edge properties, the element ends up exactly where it would have been if we had
set position:static, or if we hadn't set position at
all.


If we set top:10px, the element is shifted 10 pixels from its
original top edge. That means it moves downward. A negative value shifts the
element in the opposite direction, so we could achieve the exact same result by
setting bottom:-10px. This means it's not meaningful to specify
both top and bottom, or both
left and right. There may, however, be reasons for
specifying, for instance, top and left together, if we
want to shift an element both vertically and horizontally.


Now, this isn't very useful for creating columns, because a relatively
positioned element remains in the document flow – in the position where it
originally was. It still takes up space, but not where it's actually shown, but
where it would have been shown, had it been statically positioned.


What does this mean in the real world? Relative positioning is mostly useful
for shifting an element a few pixels in either direction, or you'll get a
"hole" in your page. There is, however, another use for it that is much
more important: A relatively positioned element counts as positioned, even if we
don't shift it a single pixel in any direction. We will soon see why that is
important.


Absolute Positioning

What people normally mean by positioning, CSS-P or layers, is
elements with position:absolute. The top,
bottom, left and right properties specify
the distance to the corresponding edge of the element. But from what?


Ironically, absolute positioning is relative. Yes, you read that right. An
absolutely positioned element is positioned relative to another element, called
the containing block. Here comes the definition of that. Take a few
deep breaths and hold on tight to the armrests of your chair.


The containing block of an absolutely positioned element is its nearest
positioned ancestor, or, if there is no such element, the document's
initial containing block.


By "positioned ancestor" we mean a structurally superior element whose
position property is absolute, fixed or
relative. So here is that important use for relatively positioned
elements that we touched on a minute ago. By setting
position:relative for an element, without shifting it at all, we
can establish a new context for its absolutely positioned children. Sounds easy,
doesn't it?


But if there is no positioned ancestor then? That's where the so-called
initial containing block comes into the picture. The CSS
standard helpfully says that this is "chosen by the user agent". ("User
agent" is the application that processes a web page, for instance a browser,
some assistive technology, or a search engine.) The standard also states that it
could be related to the viewport. In practice this means either of the
BODY or HTML elements.


Absolutely positioned elements are completely removed from the document flow.
This means they don't take up any space. Or, to phrase it differently, they
don't affect subsequent elements. We thus have to make sure ourselves that no
other content ends up underneath our positioned element, unless that is the very
effect we're after, of course.


An absolutely positioned element with top:100px is consequently
placed so that its top edge is 100 pixels from the top edge of its containing
block. In browsers that support CSS you can specify all four edges
and let the browser compute the width and the height. Unfortunately this doesn't
work in Internet Explorer, so it's almost always necessary to specify at least
the width of an absolutely positioned element.


It is perfectly legal to specify negative values for the edge properties, but
if you do, you should be very aware of what the containing block is. Otherwise
you risk putting the element completely or partially off the screen.


Fixed Positioning

We established earlier that absolute positioning is relative, so it should
come as no surprise that fixed positioning is absolute.


An element with position:fixed is positioned absolutely with
respect to the viewport (the browser window). Fixed positioning is very similar
to absolute positioning, but there are differences. The position is always
computed with respect to the viewport; the viewport is always the containing
block. The element is removed from the document flow and it stays put even if
the user scrolls the document.


Unfortunately Internet Explorer doesn't support fixed positioning. There are
a number of more or less complicated ways to circumvent that, but fixed
positioning isn't actually as useful as one may think. Sure, it's conceivable to
have a menu in the left or right column that is always visible, but most users
today expect everything on the page to move upwards when they scroll.


Finally

Absolute positioning is useful for multi-column layouts, as long as you
always know which column is longest. Since the absolutely positioned elements
are removed from the document flow, the don't affect subsequent elements.
Therefore it is very difficult to have a full-width footer appear after all the
columns.


As with any web design, you should try to use relative units with
positioning, so that the layout can adapt to different window sizes. The value
for left, for instance, should be specified in em or
%, not in px.


If you specify the width for an absolutely positioned element, either
explicitly via width in percents, or implicitly
via left and right, the standard says that it should
be computed relative to the containing block. Both Internet Explorer
and Opera get this wrong, unfortunately, and use the width of the
parent element as the basis for their computations. Gecko-based
browsers like Mozilla and Firefox behave correctly.


With all types of positioning, including relative, you should set margins and
padding explicitly, especially if you want it to look the same cross-browser.
Browsers have different standard values for these properties.


When positioned elements overlap, we can control the stacking order with the
z-index property. The higher the z-index, the closer
to the user the element ends up. Unfortunately this isn't quite as
straightforward as it sounds, since each containing block establishes its own
context for z-index. So to put one element on top of another
element, with a different containing block, you need to increase the
z-index for the first element's containing block. In
really complex layouts you can find yourself in impossible situations, if you
want to stack three elements where the middle one has a different containing
block than the other two. As far as we know, this cannot be done.


Absolute positioning is often used with DIV elements, but it's
perfectly valid to position any element.

No comments:

Post a Comment