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.
CSS Box Model and Types of Position
In order to understand positioning you first need to understand the css box model. The link in the previous sentence is a post I wrote for InstantShift about the box model. I’ll point you there for details and offer a quick summary here.
Every element in css is contained by a rectangular box, each with an area defined for the content, padding around that content, a border enclosing both and a margin outside the border that separates one box from the next. You can see it in the following image.
Positioning schemes define where a box will sit in the overall layout and how each box affects the others around it. Positioning schemes include the normal document flow, floats, and several types of positioned elements.
The css position property takes 5 values.
- position: absolute
- position: relative
- position: fixed
- position: static
- position: inherit
I’ll cover the first three in more detail below and just say a couple of quick things about the last two here.
Static positioning is the default. Any element that has position: static applied is in the normal document flow. The rules for where it sits and how it affects other boxes are defined by the box model.
A statically positioned element will ignore any values for the properties, top, right, bottom, and left as well as any z-index declarations. In order to use any of those properties your element must have absolute, relative, or fixed positioning applied.
Inherit as in all css properties is simply that the current element receives the same value as its parent element.
Absolutely positioned elements are completely removed from the normal document flow. As far as the elements around them are concerned the absolutely positioned element doesn’t exist. It’s as though the display property of the element was set to none. If you want to maintain the space so other elements don’t move to fill it you need to account for it in other ways.
You set the location of an absolutely positioned element through the top, right, bottom, and left properties. You’ll usually define only two of these, either top or bottom, and either left or right. By default each will have a value of auto set.
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.
An absolutely positioned element is positioned relative to the first parent element that has a position other than static applied to it. If no parent element up the chain meets that condition the absolutely positioned element is positioned relative to the document window. Huh?
It’s a little confusing with all the talk of relative, especially when there’s relative positioning, which we haven’t yet talked about.
When you set position: absolute on an element css says to look at the parent element and if it also has positioning (other than static) applied, the origin for the absolutely positioned elements is the top, left corner of the parent element.
If the parent doesn’t have positioning applied then go to the parent’s parent and check to see if it has positioning applied. If it does then that element’s top left corner is the origin for our absolutely positioned element. If not then continue up through the DOM until you reach a positioned element or failing that reach the outermost edge of the browser window.
Relatively positioned elements are positioned based on the same top, right, bottom, and left properties, but are simply shifted from where they would normally sit. In a sense adding relative positioning is similar to adding a margin with one very important difference. The elements around a relatively positioned element act as though that shift didn’t exist. They ignore it.
Think of it as a ghost image shifted a little out of kilter from the actual image. The relatively positioned element behaves as though it’s the ghost, while all other elements behave as though it’s the original non-ghost image. This allows elements to overlap each other as a relatively positioned element can move into the space occupied by it’s neighboring elements.
The relatively positioned element is taken out of the normal document flow, but still affects the elements around it. Those elements just act as though the positioned element is still in the normal document flow.
We don’t have to ask the question relative to what here. The answer is always the normal document flow. Kind of like adding a margin as far as the element is concerned and kind of like doing nothing as far as neighboring elements are concerned. Margin, yet not margin.
Fixed positioning acts similarly to absolute positioning with a couple of differences.
First the fixed positioned element is always positioned relative to the browser window and take the now familiar top, right, bottom, and left properties.. It’s the positioning rebel that ignores it’s parents.
The second difference is inherent in the name. Fixed positioned elements are fixed. They don’t move as the page is scrolled. You tell the element where it should be located and it never moves. Maybe not so rebellious after all.
In a sense fixed positioned elements might be akin to fixed background images where the containing block is always the browser window. If you set a background image on the body it will behave mostly like a fixed positioned element with less precision about where it’s located.
Background images also wouldn’t be able to change where they sit in the third dimension, which brings us to the z-index.
Z-Index, Breaking out of the Plane
The page is a two dimensional plane. It has a width and a height. We live in a 3-dimensional world that also includes depth and z-index is that depth. That extra dimension moves in and out of the page.
Higher z-indexes sit on top of lower z-indexes and move toward the front of the page. Conversely a lower z-index sits behind the higher z-index and recedes toward the back of the page.
Without z-index, positioned elements are somewhat boring. They have their use without that extra dimension, but with z-index applied you can do some creative things and allow one element to sit on top or behind another element. By default all elements have a z-index of 0 and negative numbers are allowed to be assigned.
Z-Index is actually much more complex than I’m describing here, but the details are for another post. For now remember the basic idea of an extra dimension and a stacking order and remember that only positioned elements can use the z-index property.
There are a few common issues you see with positioned elements and each deserves a sentence or two.
1. You can’t apply both the position property and the float property to the same element. Both are conflicting instructions for what positioning scheme to use. If you add both to the same element expect the one that appears last in your css code to be the one that’s used.
2. Margins don’t collapse on absolutely positioned elements. Suppose you have a paragraph with a margin-bottom of 20px applied. Right below the paragraph is an image with a margin-top of 30px applied. The space between the paragraph and the image will not be 50px (20px + 30px), but rather 30px (30px > 20px). This is known as collapsing margins. The two margins combine (or collapse) to become one margin.
Absolutely positioned elements do not have margins that collapse, which might make them act differently than expected
3. IE gets z-index a little wrong. In IE6 the select element always appears at the top of the stack regardless of it’s z-index and the z-index of other elements around it.
IE6 and IE7 have another z-index issue with stacking context. IE looks to the outermost parent with positioning applied to determine which group of elements is at the top of the stack instead of looking at each individual element.
1 2 3 4
<div style="z-index: "> <p style="z-index: 1"></p> </div> <img style="z-index: " />
You would expect the paragraph to be at the top of the stack, because it has the highest z-index. However IE6 and IE7 would place the image on top of the paragraph, because it sees two different stacks. One for the div and one for the image. The image has a higher z-index than the div and so will sit on top of everything inside the div.
The position property sets an element to behave according to one of the css positioning schemes. You can set values of absolute, relative, fixed, static (default), and inherit on positioned elements.
Positioning schemes, including css positioned elements, define the rules of where a box sits within a layout and how neighboring elements are affected by the positioned element.
A z-index can only be applied to positioned elements. It adds a 3rd dimension to a page and sets the stack order of elements
The position property seems easy to grasp, but it works a little differently than it looks on the surface. What you might think is relative positioning is more likely absolute positioning. You’ll generally want to use floats when developing a layout and use positioning on specific elements that you want to break out of the layout.