Looking for the lessons? Get started!
Positioning elements for page layouts.
The entire Web Design Principles section can be accessed through the menu below.
Unfortunately, not everyone's browser will support the spiffy JavaScript menu behind that innocent-looking button. If your browser won't display the menu, just click on the button and you'll be taken to a separate page with the entire menu displayed in clear, non-JavaScript HTML.
Position is nine-tenths of the law. — Maggie Tuck
Positioning elements in an HTML page is usually done through the CSS stylesheet. There is some argument over how semantically correct this is, since CSS is supposed to be about a page's style and appearance, and HTML is about content and structure, but I'm not going to rehash that argument here. Suffice it to say that when you consider the issue, it's plain (to me) that CSS is the right venue to handle positioning. You are free to disagree.
The key to understanding positioning is understanding the box model of Web design layout. We touched on the concept in another page:
More about block and inline elements.
If you haven't read the page above, you might go back and look it over before moving forward on this page.
Much of the information on this page comes from two excellent books by Ian Lloyd and Craig Grannell, and from several well-regarded Internet sources: Tommy Olsson, Mike Hall, Steven Bradley, Rob Glazebrook, Kilian Valkhof (the second part of Valkhof's article is here), Chris Coyier, and BarelyFitz Designs, along with bits from other sources. As always, the sources contain far more information that I have included here. You should definitely check them out on your own.
Bradley notes:
When people are new to CSS layouts there’s a tendency to gravitate toward positioning. Positioning seems like an easy concept to grasp. On the surface you specify exactly where you want a block to be located and there it sits. Positioning is a little more complicated than it first appears though. There are a few things that can trip up a newbie and a few things to understand before positioning becomes second nature. You can do some great things with positioning, once you develop a deeper understanding of how it works.
Maybe a bit obvious and even trite, but it's true, and therefore worth quoting.
And Valkhof gives an excellent summation of the quality of "flow" as affected by positioning:
With positioning, the elusive "Flow" of CSS positioning comes into play. The flow in CSS is the logical way in which elements get placed on your screen. For example, when you turn off the CSS on this page, you see the HTML in its original order. That order is the flow, and dictates which element gets rendered and placed where. It's very simple: the flow of a page is from the top of the HTML to the bottom of it.
The Box Model
The box model is, at its core, very simple. Every element on a Web page, big, small, or in-between, is a box. Period.
There are a ton of illustrative images on the Net, but I was lucky enough to secure permission to use this one from the owner, Craig Cook. (Craig's excellent ruminations and lessons on Web design are found in this and other pages of this site as well. He even sent me a better version of the graphic than the one appearing on his site, one I've reproduced here.)
Oooh, it's all three-dimensional and stuff....
But what does it really mean? Here's Cook to explain it all:
Working from the outside in and back to front, we have an invisible margin area between the edge of this element and its adjacent elements. Inside the margin, we can apply a background color, and a background image will overlay that. Padding is invisible space between the edge of the box and its contents, and the background will show through the padding area. Overlaying all this is a border, outlining the visible edge of the element.
Steven Bradley gives us the following information:
width of containing block (box) = margin-left + border-left-width + padding-left + width + padding-right + border-right-width + margin-right
height of containing block (box) = margin-top + border-top-width + padding-top + height + padding-bottom + border-bottom-width + margin-bottom
More about margins and padding.
Mike Hall gives us some more clarification:
Margins, borders and padding are all optional but for purposes of calculating positions and sizes they are given a default width of zero if not specified. Different widths can be set for each individual side (top, right, bottom and left) if desired. Margins can even have negative values. The width and height of each box is equal to the width and height of the outer margin box. Note that this is not the necessarily the same as the width and height of the content area. A box can contain any number of other boxes, creating a hierarchy of boxes that corresponds to the nesting of page elements. The browser window serves as the root element for this hierarchy.
And web developer Rob Glazebrook sums it up for us:
Anything that starts with a <tag> and ends with a </tag> is a box (container, whatever). So a <p> tag is a box, which is maybe inside of a <div> box, inside of a <body> box, inside of a <html> box. And with CSS, what you're really doing is manipulating the size, shape, color, decoration and so forth of that box and its contents.
Basically, every element in your stylesheet is, in your HTML page, surrounded by a box. The dimensions are set depending on the content and the characteristics of the element. We can use the width and height properties in our CSS markup to define the box boundaries in specific manners.
Web designer Chris Coyier writes that understanding the "box model" concept was his "ah-ha moment", where he began to comprehend the underlying paradigm of CSS structure. He writes:
It was a combination of these [following] concepts that were my "Ah-ha!" moment.
Every page element is a box.
I can control the size and position of those boxes.
I can give those boxes background images.
Sounds simple, but those things still feel powerful for me today.
Okay, now let's get our feet wet.
There are two main types of boxes, block and inline.
More about block and inline elements.
Bradley writes:
Block level boxes are laid out vertically one after the other. If you have two block level boxes next to each other in your html, the second will sit below the first. Inline boxes on the other hand are laid out horizontally. An inline box will always sit to the right of the box that precedes it, assuming there's enough room in the containing element. Inline boxes will wrap though. They will start to the right of the previous box and fill whatever horizontal space is remaining. They will then wrap to the next line and again move to fill the horizontal space. A block level box would automatically drop to the next line before filling any space.
You might read Bradley's excellent examination of the box model — the source of the above quote — for more information.
For now, just remember:
Block-level elements "stack" vertically, one on top of the other, like the floors of an apartment building:
Inline elements will lay horizontally beside one another unless the page width forces one element to move to the next line, like rows of bricks:
We can use margins and padding to set the width and height of our "box" elements, and we can use borders, background colors, and background images to add visual interest (in technical terms, "spiff it up"). The background colors or images we use will show behind the padding and borders, but not the margins.
How do we know the dimensions of a particular box? Well, there are defaults. If you use what's called a "global reset", your defaults have most likely been set to zero. If not, the browser sets its own defaults, and as you might imagine, they vary from one browser to the next.
For setting dimensions, we can best see that in an example.
Let's say we have a div element that is defined as 100 pixels wide:
.example { width: 100px; }
We can add 10 pixels of padding to the box if we like, and even a 5px border:
.example { width: 100px; padding: 10px; border: 5px solid black; }
The total width of the .example
element is 130 pixels. Howzat? Simple math.
5px + 10px + 100px + 10px + 5px = 130px
The borders on each side (left and right) are 5px apiece. The padding on each side is 10px apiece. The central element is 100px. Total that on your calculator or in your head and you get 130px.
Why is that important? Well, if you use a background image that is 115px wide, you'll see quickly enough that the dimensions of the .example
element have 15px that aren't filled by the image. That won't look right.
There's something else to remember about setting widths. If you don't set the width on a block-level element (and it is set to either static
or relative
position), then the width is 100%, just as the usual default is. The padding and border will push in on that 100% width. However, if you set the width to 100%, then the padding pushes the box outward. Coyier explains:
The lesson here being that the default width of a box isn't really 100% but a less tangible "whatever is left". This is particularly valuable to know, since there are lots of circumstances where it is immensely useful to either set or not set a width.
In general, it's best to set widths. Coyier observes:
[T]he best thing to do is always set a width on anything floated, absolutely positioned, or fixed positioned to avoid cross-browser problems.
Need more? Glazebrook gives us a terrific metaphor, which I'm just going to steal like I'm stealing his television (except I'm crediting it, and recommending that you read his entire article on the subject).
[H]ere are the most basic properties you have to worry about when dealing with the box model: border, background, padding, width and margin. We'll go through these properties one by one below. And to help it make sense, we'll relate it to how you'd pack a box in real life.
- Border: This is the box. When you're starting out, it helps to think of the border as the outline of a real box. It can have different thicknesses (widths) and colors, but it's basically just a rigid structure you put things into. Of course, you can also have a border of zero, but it still helps to think of the border as the outermost part of your box, even if it isn't there.
- Background: If you apply a background to something, it stretches from one side of the border to the other, covering the entire inside of your box. Also, if you apply both a background color and a background image, the image will sit on top of the color.
- Padding: Think of padding as the bubble wrap or packing peanuts you'd add to a box before shipping it somewhere. Padding lies between your border and your content. This is the sanest property of the lot.
- Width: This is the width of your content inside your box. This can be somewhat counter-intuitive at first, because it is not the width of your border. It's the width of the stuff inside your border, and inside your padding. So if you set a width of 400 pixels, with 20 pixels of padding on both sides, and a 5-pixel border, your actual 'box' would be 400+20+20+5+ 5 (otherwise known as 450) pixels wide.
- Margin: Margins exist outside of our hypothetical box, around your border. Think of it as space outside your box that you're deliberately leaving empty, as if the stuff inside the box were volatile, dangerous, stinky, or otherwise something you'd want to give a wide berth. So if you took our box from the width example and gave it a 10 pixel margin on every side, we’d now have a 450 pixel wide 'box' taking up 470 pixels of space.
And that's really all there is to the box model!
Well, not quite. As Glazebrook (and everyone else) notes, Internet Explorer treats the box model a bit differently. (How did we know it would be IE and not a different browser?) Actually, it's not so bad: if you use a proper DOCTYPE, and use IE 6 or later, you won't run into a problem. IE 5.5 and earlier suffer from what's called the "broken box model." So unless you are forced to code for that antiquated and rapidly disappearing browser, don't worry about it. And if you do find yourself coding for IE 5x, you can start by reading Glazebrook's how-to on coping with the problem.
Collapsing Margins
Sometimes, margins between two box elements "collapse," resulting in the larger of the two margins being used and the other one "collapsing" to a de facto value of zero. Very uncool.
I'm not going to go into this little problem, but I'll give you a link to an excellent reference article by Tommy Olsson and Paul O'Brien that will tell you what you need to know, including how to keep it from happening.
The Basics of Positioning
There are four types of positioning in CSS:
- static;
- relative;
- absolute; and
- fixed
Or in CSS code terms:
position: static; position: relative; position: absolute; position: fixed;
That's all well and good, but what do the terms mean? And just as importantly, what do they do, and how can I use them effectively in my designs?
Well, the terms are confusing. As my friend Tommy Olsson writes:
Most of us probably regard this matter from a layout point of view, from which the names seem quite odd. A static element isn't static at all, it moves around as we scroll the page. A relatively positioned element is only relative to itself. An absolutely positioned element is not absolute, but relative to some other element. And a fixed element is both absolute and static.
But the W3C didn't assign these names from a layout perspective. The folks in that group assigned these names from a "document" perspective.
More about documents and tags.
Within the HTML document, a static element is "static" — unmoving — within the document flow. A relatively positioned element is "relative" — to itself. An absolutely positioned element is indeed positioned "absolutely" within its container and removed from the document flow. And a fixed element is "fixed" with respect to the document flow.
By helping you understand the different kinds of positioning, I can help you make informed and proper decisions as to when to use static, relative, absolute, and fixed positioning in your designs.
So let's figure them out. But we won't start by defining the four positioning states, not just yet.
Setting the Position Property
CSS gives us the position property as shown above. It also gives us the inherit value:
position: inherit;
Descendant elements — those coming below the positioning rule or selector in the stylesheet — do not inherit that positioning, but position: inherit
forces inheritance.
More about CSS selectors, properties, and values.
Any HTML element can be positioned, including all block and inline elements.
Position properties can also be modified with the following properties:
- top
- right
- bottom
- left
The Overflow Property
A property that goes with the idea of the rectangular box is the overflow property. Just like when you're packing your belongings into cardboard boxes and trying to ram too much into them, a CSS "box" can have its content "overflow" into other areas of the page layout. The overflow property helps control that.
Web ninjas Tommy Olsson and Paul O'Brien make the following observations:
The default behavior is to make the overflowing content visible, but it can be changed so that the content is clipped to the confines of the element’s box, optionally providing a mechanism for scrolling the content.
If the overflow property is applied to the body or html elements in an HTML document, the user agent [the browser or other Web utility] may apply it to the viewport. This does not apply to XHTML, though.
Not that we're worried about XHTML in these pages, but it's still good to know.
There are five values for the overflow property:
- visible (the default)
- hidden
- scroll
- auto
- inherit
There are two other related properties, overflow-y
and overflow-x
, but they are CSS3 properties that are widely, but not universally, accepted. We won't examine them here.
overflow: visible
Since this is the default value, you will rarely, if ever, use this, unless you have to override a previously set property. Basically, it allows content that "overflows" out of a box container to remain visible.
Say you have a containing element that is 300px wide. You put a banner graphic that's 480px wide in the containing element. It will overflow out of the box and remain visible. Same with textual content; if the container is 300px in height, but you write more text than will fit in the container, it will "overflow" downward out of the box and remain visible.
The overflowing content will not affect the flow of the document, i.e. it won't shove other elements aside to present itself.
Occasionally, margins can collapse in elements using the visible
value. That doesn't happen when other values are being used.
overflow: hidden
The opposite of the visible
value. Whatever "overflows" out of a container is hidden from sight. This can work well in a particular design, but will not be available (think accessible) to anyone unless they view the source code. Web designer Chris Coyier gives a pertinent example:
So for example a user has their default font size set larger than you would expect, you may be pushing text outside of a box and hiding it completely from their view.
Something to be mindful of.
overflow: scroll
The "overflowing" content is not visible, but the browser provides scrollbars that allows the content to be seen if the user desires. I use this in this site, when the code examples stretch past the size of the container.
One nice aspect of this value is that it allows for overflowing content to be printed.
overflow: auto
This allows the browser to determine whether the overflow content requires scrolling. If scrollbars are not needed, they are not displayed.
overflow: inherit
All this does is forces the child element to inherit the overflow value from the parent element.
Float Clearing
One oddity of the overflow property is that it can be used to clear floats.
Well, two values can clear floats: auto or hidden.
Setting an overflow value doesn't clear the float at the element, it self-clears. In real-world terms, the element with the overflow applied extends as large as necessary to enclose child elements inside that are floated. If you want to do this, don't declare a height.
Coyier provides some excellent visual examples that illustrate the various values.
There are a number of minor browser quirks associated with the overflow
property. Most of them, naturally, are found with Internet Explorer. Coyier's page details the various bugs and gives some information as how to quash them.
Browser Bugs
The overflow
property is quite buggy in several browsers.
Internet Explorer 6 has a number of oddities. It won't apply a value specified for the body element to the site as it displays in the viewport, if the overflow value on the html
is visible
. Also, it increases the width and height of the element when the value is visible
, instead of allowing the content to overflow as it should. And, if the value is auto
, hidden
, or scroll
, and the element's width is specified as auto
, the width will increase to avoid overflow.
Internet Explorer 7 and below (yes, this includes IE6) exhibits the following: in a relatively positioned child element whose parent is set at either auto
or scroll
, the element will behave as if the position were fixed;
while if the overflow value is hidden
, a relatively positioned element will be visible if the generated box lies outside the parent's box. Also, IE7 and below does not support the inherit
value.
IE7 only, with auto
, hidden
, and scroll
, the values cause an element to gain a layout value.
Internet Explorer 8 only has a number of distressing bugs that occur when the overflow property is combined with max-width
or max-height
. The Hilbrand Edskes site documents a number of test cases.
Opera 9.5 and 10 both have a bug in which a positioned parent container set to overflow other than visible
, and also has an absolutely positioned child element, causes a scrollbar to appear on the viewport if that child element's top position is greater than the viewport's height. (Not the most easily comprehended bug!)
Static Positioning
The static positioning value is the "default" value for every HTML element. If you don't give an element a different positioning value, it will be positioned as a static element. You won't use position: static
very often, except to undo an earlier positioning rule. A (bad) example:
body { position: absolute; } #footer { position: static; }
As unlikely (and insane!) as it would be to position everything in your body
as absolute, this example serves a purpose: to show you how you would make your #footer
revert to the default static status.
Statically positioned elements appear in your displayed page based on whatever statically positioned content appeared before them. Modified by margins and padding, the elements still stay in place with respect to the other content. If you don't change anything's positioning, you often end up with a single "stack" of static content, like a big stack of flapjacks, posed one on top of the other in a big, boring vertical column.
Okay, maybe less boring and a bit tempting....
Want to be even more confused? Elements with static positioning can be either block-level or inline elements. The element itself will determine the block or inline status.
Coyier writes:
Static doesn't mean much, it just means that the element will flow into the page as it normally would. The only reason you would ever set an element to
position: static
is to forcefully remove some positioning that got applied to an element outside of your control. This is fairly rare, as positioning doesn't cascade.
Relative Positioning
Like most things worth doing, relative positioning takes some thought and effort to grasp properly. Relatively positioned elements are positioned in relation to itself. Say what?
Coyier writes:
This type of positioning is probably the most confusing and misused. What it really means is "relative to itself".
Maybe we'll let Olsson explain it, in what he calls "layman's terms."
The box generated by the element is laid out just as it is for static elements. Then the rendered box is shifted horizontally and/or vertically, according to the values of the top, right, bottom, and left properties. But here's the tricky part — as far as the rest of the document is concerned, the box is still in its original place! It is laid out where it should be, and it will occupy that position in the document flow. It's only the rendered box that is shifted, relative to that original position. If we move it a large distance, we will leave a hole in the document.
Hmmmm. Let's let Valkhof take a stab at it:
This value is very similar to
position:static
, with one vital difference: While a rendered element does get the width and height of the element, it doesn’t have to occupy the space designated for it. The properties top, right, bottom and left allow you to shift it away from that space. The offset here are the borders of the designated space.
Since all of this is the case (and it is, as counter-intuitive or just plain confusing as it may seem), we can't use position: relative
for columnar layouts. And if used in its simplest form, it will merely move elements around a few pixels. So, useless, right? Not at all. It has a side effect that clever Web designers have long used to their advantage.
Remember those top, right, bottom, and left properties? These "push" the selected element (think boxes, remember) out of its original, static position. How so?
Setting a relatively positioned element 20 pixels from the top:
#element { position: relative; top: 20px; }
moves the "box" 20 pixels down from where it would have been had we not futzed with the positioning.
(Since we can use negative values, we could achieve the same effect with this:
#element { position: relative; bottom: -20px; }
although we don't usually do it this way — it's just needlessly complex more often than not.
Top and bottom positioning cancel each other out, as do left and right positioning. They don't work together. However, top and left, top and right, bottom and left, or bottom and right, work beautifully together.
This code:
#element { position: relative; top: 20px; left: 60px; }
positions the specified element 20 pixels from the top and 60 pixels from the left (or 20 pixels towards the bottom and 60 pixels to the right, if you prefer).
Absolute Positioning
Tommy Olsson writes:
An element with
position:absolute
is removed from the document flow, which means the rest of the document acts as if the element weren't there. It won't affect subsequent elements. Instead, it could end up layered over other elements, unless we make sure it doesn't.
And Olsson's partner in crime, Paul O'Brien, gives a very detailed article on the evils of absolute positioning, including a nice compendium of bugs caused by this position value.
The removal of the absolutely positioned element from the document flow is a key to remembering the uses, and pitfalls, of absolutely positioned elements. Many, many Web designers, including sophisticated professionals, routinely rely on absolute positioning for, well, darn near everything. And many times, it gives them what they want. You can position elements precisely where you want them, with pixel-perfect precision. You can even lay out columns. However, absolute positioning has some major drawbacks.
As we keep saying, any absolutely positioned element is removed from the document flow. The rest of the page ignores the absolutely positioned element and goes about its business presenting its content as if the absolutely positioned element doesn't exist. The absolutely posotioned element can, and so often will, end up sitting on top of another portion of the document, layered over other elements as Tommy writes. There are times when we want this to happen, but more often it isn't the effect we want.
Or even more maddeningly, you get your page positioned perfectly with one or more absolutely positioned elements. Looks great. Then you change the screen resolution, and everything goes to pot. The relative and statically positioned elements adapt to the new resolution, but the absolutely positioned elements ... don't.
(It's also worth knowing that absolutely positioned elements with no width only have the width their content requires. An absolutely positioned paragraph of one word is wide enough to contain that word and no more. Same with more words, or an image, or whatever. This continues until the parent element's width is reached, or until the absolutely positioned element reached 100% of the page width. Some browsers are funny about handling this.)
Steven Bradley writes:
The key to understanding absolute positioning is understanding where the origin is. If top is set to 20px the question you should be asking is 20px from where.
We can still use the top, right, bottom, and left properties, but in a much different way than they function in a relatively positioned element. The four properties now specify the positions of the four edges of the absolutely positioned "box" element. You can use pixels or ems (or other, less used) units of length to specify the values of these properties. You can even use percentages, but that's complicated — percent values for top and bottom refer to a percentage of the height of the containing block, while for right and left it refers to the width of the containing block.
In fact, the whole idea of absolute positioning is made even more complicated by the concept of the containing block. Hitch up your pantaloons and get ready for a ride....
The Containing Block
The concept of the containing block applies to more than just absolutely positioned elements, but it's a key concept in working with absolute positioning, so we'll tackle it right here. Tommy quotes the CSS 2.1 specification:
If the element has "position: absolute", the containing block is established by the nearest ancestor with a "position" of "absolute", "relative" or "fixed" ... If there is no such ancestor, the containing block is the initial containing block.
What in the heck does that mean? What's my ancestors have to do with anything? Granny, are you controlling my Web page?
Thankfully, Granny isn't involved in this.
The containing block for an absolutely positioned element is its nearest positioned "ancestor" element, say, a #body
or a #div
that has a position selector attached to it. If none exist, the containing block is, essentially, the html
element. Tommy writes, succinctly enough:
In other words, we can assume that if there is no positioned ancestor for an absolutely positioned element, the containing block is the document itself.
Here's a quick example:
<div class="whatever"> <p>Some content.</p> </div>
The #whatever
div creates a containing block for the paragraph. In its turn, the p
element creates a containing block for the text "Some content".
One of the cool effects of the containing block paradigm is that when a relatively positioned element can become the containing block for an absolutely positioned element. In that case, we can exert control over the containing block.
When an "ancestor" element is positioned relatively, we can position an element occurring after that element absolutely. The containing block doesn't move with the position: relative
affixed to it, it just allows us to control its "descendant" element's absolute positioning. Now we can use the top, right, bottom, and left properties to adjust the element within the corresponding edge of the containing block. This:
left: 10px;
has the left-hand edge of the absolutely positioned element is located 10 pixels from the left-hand edge of the containing block.
Naturally, Internet Explorer 5 and 6 both choke on this to an extent. Tommy explains:
In a CSS2-compliant browser, we could specify all four properties to give both the position and the dimensions of our absolutely positioned element. Unfortunately, IE5/6 do not support this, so in the real world, we will often need to specify one vertical position (either top or bottom) and one horizontal position (left or right) and then set the width property and, sometimes, the height property. These bugs also apply to values specified as percents. In IE5/6, they do not apply to the dimensions of the containing block, but of the parent block. As we have seen, those can be two very different things. The percentage bugs are also present in Opera, up to and including version 8. They are fixed in Opera 9.
I don't worry too much about bugs in obsolete versions of Opera (and Firefox), because their users tend to update their browsers in a very short time after the release of a new version. Internet Explorer users, on the other hand, are stuck with the version of the browser that came with their copy of Windows unless they buy a new computer, upgrade their operating system, or otherwise obtain an upgraded version.
It's also worth noting that if you have a block element relatively positioned, it establishes itself as a new containing block. Mike Hall writes: " Positioned elements within it will use the 'offset' position of that element as a base for positioning. In other words, the offsets of descendant elements are compounded." If you have an inline element relatively positioned, it does not establish itself as a new containing block, but uses the offsets of its own containing block. Hall again: "If the relatively positioned element is an inline element, its offsets are not combined with the offsets of its positioned descendants. Instead they are based on the same containing block used by the relatively positioned element."
One more thing: you have another value for the top, right, bottom, and left properties, called auto
:
left: auto;
This tells the browser to place the absolutely positioned element where it would be placed if it were positioned as a normal, i.e. static, element. This can be very useful.
This is quite confusing; I suggest you follow up by perusing Tommy Olsson's article explaining this in more detail.
Nesting Absolutely Positioned Elements
Ian Lloyd gives us a nifty little example of nesting absolutely positioned elements one inside the other.
If we start with an absolutely positioned block 200 pixels from the top and 200 pixels from the left:
#redblock { position: absolute; top: 200px; left: 200px; background-color: red; width: 100px; height: 100px; }
you get, well, a small red box 200 pixels down and in.
Here's the HTML code:
<div id="redblock"></div>
(Notice that the div does not contain any content.)
Now, let's say we want a smaller yellow box to appear inside our red box.
We might want to put the yellow box 220 pixels down and 220 pixels in. We would be wrong.
First, we need to place the div containing the #yellowblock
ID inside of the div containing the #redblock
ID. Like so:
<div id="redblock"> <div id="yellowblock"></div> </div>
This means that the #yellowblock
div inherits the positioning of its parent element, the #redblock
div.
Now, to make this work, we create the #yellowblock
CSS. We'll place the yellow box 20 pixels down and 20 pixels in from the top left point of the red box, and make it half the width of the red box:
#yellowblock { position: absolute; top: 20px; left: 20px; background-color: yellow; color: red; width: 50px; height: 50px; padding: 5px; }
Here's what Ian's nested elements look like.
Nifty, huh? Ian Lloyd has given us a great visual example of how absolutely positioned elements can work in concert with one another.
You might want to play with the code a bit in your own page (or just copy and paste the source code of the example page into a blank HTML file). Try making the #yellowbox
width and height 100px. Try changing the positioning. Have some fun with it.
Using Absolutely Positioned Elements Inside Relatively Positioned Containers
One of the key techniques in making CSS layouts is putting absolutely positioned elements inside a relatively positioned container.
Essentially, the key to understanding this is figuring out that the absolutely positioned elements position themselves inside the relatively container, and not the body of the page. That is a simple yet key concept.
The following graphic (actually a screenshot of a page I made to illustrate this point, based on an example by web designer Chris Coyier), shows a medium-sized containing element with a black border around it, and three smaller orange elements within. The container is relatively positioned, and the smaller orange elements are absolutely positioned within the container, with the values shown in the screenshot.
When the browser is resized, the elements stay within the absolutely positioned container instead of sticking to the browser window (or whatever it does on its own).
Coyier gives several illustrative examples of this technique, including some nifty uses for it.
Fixed Positioning
If you have figured out absolute positioning, you pretty much understand fixed positioning. (Mike Hall actually classifies fixed positioning as a variant of absolute positioning.) The biggest difference is that for an element with fixed positioning, the containing block is always the initial containing block — generally, the html
element that defines the entire HTML document. The top, right, bottom, and left properties always reference the edges of the browser window (the viewport), or if you're creating a print stylesheet, the paper.
Elements with fixed positioning don't move. Period. If you've seen pages with fixed navigation schemes, for example (here's a demo of one from CSS guru Soh Tanaka, and here's the main page for that demo), they use fixed positioning to make it all happen.
Coyier writes:
The viewport doesn't change when the window is scrolled, so a fixed positioned element will stay right where it is when the page is scrolled, creating an effect a bit like the old school "frames" days.
Naturally, Internet Explorer 5/6 poses a problem with using position: fixed;
. Neither browser recognizes the selector at all. That's why you don't often see designers using this one.
(Does anyone besides me find those little fixed "feedback" or whatever boxes annoying?)
The Bluelounge site uses fixed positioning on its left sidebar. Take a look and see how, when you scroll down, the sidebar remains in place.
Coyier writes of the site:
This site is a perfect example [of fixed positioning] since it exhibits both good and bad traits of fixed positioning. The good is that it keeps the navigation present at all times on the page and it creates and interested effect on the page. The bad is that there are some usability concerns. On my smallish laptop, the content in the sidebar is cut off and there is no way from me to scroll down to see the rest of that content. Also if I scroll all the way down to the footer, it overlaps the footer content not allowing me to see all of that. Cool effect, can be useful, but needs to be thoroughly tested.
The Z-Index
Whether you're using relative, absolute, or fixed positioning, it's entirely possible that you have "boxes" on top of one another to one extent or the other: overlap. If we want to control which box is on "top" in our display, we can use the z-index property.
(This has no effect on elements positioned statically.)
The z-index property is a numeric value, positive or negative. To understand what it does, we have to think in three dimensions for a moment. (You might jump up to Craig Cook's nifty illustration of the box model for a visual reminder of how this works.)
Let's take a look at the relevant portion of the W3C specifications to try to comprehend the z-index:
In CSS 2.1, each box has a position in three dimensions. In addition to their horizontal and vertical positions, boxes lie along a "z-axis" and are formatted one on top of the other.
Ugh, I shouldn't have cut all those math classes… I'm going to let Tommy explain this again, since his understanding of the property is much deeper than mine:
A computer screen is (currently) two-dimensional. It's a flat area with a width and a height, onto which we can render our CSS boxes. But CSS actually works in three dimensions. The X and Y axes are our normal horizontal and vertical axes, respectively. The Z axis is perpendicular to those two. Think of it as pointing straight into the front of and out the back of the screen. The higher the value of the z-index property, the closer the element is to the user. This is called the stacking level.
Tommy doesn't go into intensive detail about stacking levels and stacking contexts, for which we can be grateful, I suppose. A rule of thumb about this is that you can assign a "stacking level" — the order of the stack in three dimensions — using the z-index property.
I'm going to shamelessly steal Tommy's example to illustrate this effect. Given the following HTML code:
<div id="first"> <div id="a">...</div> <div id="b">...</div> </div> <div id="next"> <div id="c">...</div> <div id="d">...<div> </div>
and the following CSS rules:
#first { position: relative; } #next { position: relative; }
Both the first and next divs are relatively positioned. Therefore, they are the containing blocks for any absolutely positioned "children," or "descendent" elements.
The inner, "child" divs (a, b, c, and d) are relatively positioned. Now we can influence the stacking order for the four letter divs using the z-index. Like so:
#a { z-index: 4; } #b { z-index: 3; } #c { z-index: 2; } #d { z-index: 1; }
Since the a div has the highest (therefore the highest priority) number, it will appear on "top" in the stack. The d div will be the last, or "bottom" element. The actual numbers used aren't important — you can achieve the same effect by using these values:
#a { z-index: 9999; } #b { z-index: 100 } #c { z-index: 10; } #d { z-index: 1; }
Tommy gives some more vital information:
We can also affect the stacking order of first and next, should they overlap, because they live in the same stacking context. But what if we want next or c to slide in between a and b? Now we’re out of luck, because next and c exist in different stacking contexts from a and b, and there is no way that we can insert them between those two. Likewise, we cannot intersperse child elements of b with child elements of a, because a and b establish their own separate stacking contexts. Just as knowledge of the containing block is extremely important for absolute positioning, the stacking context is important when using z-index.
If you use negative numbers in your z-index values, those designated elements will appear behind other elements, whether they bear a positive z-index value or are undesignated. Some designers like to use this to make sure a particular element is always below everything else:
z-index: -9999;
Web designer Louis Lazaris gives us more info on the z-index in an informative Smashing Magazine article, including a look at the use of z-index with JavaScript, implementation problems with IE and Firefox, and an array of varied elements and creations that hinge on the use of the z-index property.
And designer Tim Kadlec takes a deeper look at the concept of "stacking" with the z-index.
If you prefer a video approach to learning about the z-index property, check out Chris Coyier's screencast titled, appropriately, "How z-index Works".
Vertical-Align
Although many people only consider the vertical-align
property only useful in tables, it can actually be used to align elements such as images.
It doesn't work on block-level elements:
More about block and inline elements.
you can't affect a div
inside another div
, for example.
But there are some nifty things we can do with this property, mainly with inline elements such as images.
There are ten — count 'em, ten — values to vertical-align
:
- baseline (the default)
- sub
- super
- top
- text-top
- middle
- bottom
- text-bottom
- length
- a value in percentage
In the SitePoint Reference, Tommy Olsson and Paul O'Brien give us the following about the values:
A length value raises or lowers (depending on its sign) the box by the specified distance.
A percentage value raises or lowers (depending on its sign) the box by the distance specified as the percentage applied to the element's line-height.
For inline blocks, the baseline is the baseline of the last line box in the normal flow. If there isn't one, the element's bottom margin edge is used.
Let's look at how this positioning property can be used for images, courtesy of web Ninja Chris Coyier. Refer to his site for a number of excellent visual illustrations.
Say you're trying to align an image next to a string of text, like this site does:
This paragraph has a cute little CSS icon to the left of it.
I don't use a different vertical-align
value on this, because the image sits nicely (to my eye) alongside the text with the default baseline
value in effect.
Baseline
For the baseline
property, the image lines up with the bottom edge of the text (not the descenders, like the bottom vertical piece of the p or the q.
Middle
This value attempts to set the image in place relative to the middle, or the center, of the text. If you're putting the icon in the middle of a paragraph, and it's taller than the text, this value will push the following text lines down to accomodate the icon.
Text-bottom
The biggest difference between this and the baseline
value is that text-bottom
lines up the bottom of the image with the lowest point of the text: the p or the q descenders.
Text-top
The exact opposite of text-bottom
, text-top
aligns an image to the very top of the text: say the top of a capital T or other letters.
Top and bottom
These values align images with the very top of whatever's in the text line — text, images, whatever. Coyier explains:
So if there were two images on the same line, of different heights and both larger than the text on that line, their tops (or bottoms) would align regardless of that text size.
Sub and super
These are subscript and superscript, respectively, so they set the image slightly below (or above) the text.
Final Thoughts
Tommy has provided us an excellent example page showing all of the positioning schemes employed in the same document. IE 5/6 users will not see it properly, because those browsers are broken. Mike Hall has also provided some nifty examples. The folks at Onyx Design have provided some nifty examples that illustrate the various types of positioning. And Peter-Paul Koch gives a primer on the various display elements as well as a very cool testing area (scroll down to the end of the article).