Css Positioning

From CSS Discuss

Jump to: navigation, search

Positioning is one of the more confusing concepts in CSS. There are several ways to change the rules of how an element is positioned, and all of them give different types of control to the designer.

Note: This article discusses the theoretical differences. Browser issues and bugs are not included in this discussion.

Contents

Using the box model for positioning

The first thing to consider is how to use multiple elements of the box model[1] to move objects around. You may run into a situation where one element's text needs to be aligned to the text of another, but the other element is inside a container positioned using ems, and that element has a 1px border.

Keep in mind that every block-level element has three different dimensions on every side -- margin, border and padding. You can use this to create apparent spacing such as "10% + 2em + 5px" or "-.5em + 2px", by applying different dimensions to different properties.


The positioning methods

There are 5 basic ways to position an element:

  • Static positioning -- the way it normally works
  • Absolute positioning -- stick the content wherever
  • Relative positioning -- nail down absolute content
  • Floating -- slide content into its own corner
  • Fixed positioning -- overlay content on the window

Static positioning

This is the positioning model browsers normally apply to content. If your content isn't floated or positioned in another way, then it is statically positioned. Take a chunk of HTML, show it in a browser with no styles, and you are seeing a bunch of content that is being statically positioned.

So why make a big deal about static positioning? It is perhaps the most underrated way to position items. It is the most robust method of layout. No matter how small or large the font size is, how wide or narrow the page gets, the content will still flow one piece after the other, whether you look at block elements like paragraphs and lists, or inline elements like links. Unless you are dealing with a really buggy browser, you can't break it.

Static elements can be moved by applying margins, padding and borders. By adjusting these properties, the static content can be shifted away from where it would normally lie, as well as shift other content away from the element with the margin/padding/border. Dimensions can also be set on block-level elements, and line-heights on inline elements, to change how the element relates to other elements, although percent-based heights get tricky -- see information about percentages in heights in the W3C specifications.


Keep in mind that changing horizontal margins changes the width of that element without you having to define a width. This can be useful if you want a <div> to have children with percentage-based widths, for example, or you want something to have a width that isn't easily defined, such as 100% - 2em. With code like

<style type="text/css">
    div {
        border: 1px solid red;
    }

    p {
        width: 100%;
        background-color: blue;
    }
</style>

<div>
    <p>Hello, world!</p>
</div>

you get very different results, depending on if you apply margins versus padding on the <div>.

Static positioning, along with relative positioning, is the only context in which display: inline does something (disregarding its bug-fixing properties in Internet Explorer). Making things absolute, fixed, or floated turns inline elements into block elements.[2] Converting a block element to an inline element, or an inline element to a block element, is a key design tool used especially for defining navigation systems. See the top navigation for CSS-Discuss for an example of using inline styling on the block elements of an unordered list, for example.

Absolute positioning

Absolute positioning takes an element "out of the flow". This means that the rest of the content behaves as if that absolute element doesn't exist, even though that element is visible on the page.


For example, if you have three paragraphs, and the middle one is absolutely positioned, the page behaves as if we removed that middle paragraph from the page. The last paragraph moves up to fall immediately below the first paragraph. Then the middle paragraph appears right where it was before, so now it looks like the middle paragraph is overlaid on top of the bottom paragraph.

Absolute positioning is a good way to take content and place it somewhere that has no relationship to the content around it. Drop-down menus are a good example. They are stuck at the top of the page, at a specific coordinate, even though the HTML might be defined at the bottom of the page.

The nice thing about absolute positioning is that it doesn't care what the rest of the content does on the page. That can be a bad thing, too, though, when you want to absolute position something but you don't want it to overlap something else. Absolute positioning is challenging when you don't want it to overlap other content. An example of this issue is a page with absolutely positioned left navigation and a full-page-wide footer. If the left navigation is longer than the content, the left navigation could overlap the footer. For situations like this, we may want to use a different positioning model.

Using dimensions to absolutely position elements

Absolutely positioned elements use the properties top, right, bottom and left to identify how they are positioned relative to their containing block. (We'll talk about containing blocks when we talk about relatively positioned elements.)

Normally, absolutely positioned elements are contained within the HTML (root) tag. So top: 0; left: 0; would stick the element in the top-left corner of the page. You can also put one absolutely positioned element inside another, and the outer element will become the inner element's containing block. Now top: 0; left: 0 on the inner element will stick it to the top left corner of the outer absolute element.

When positioning an element, don't forget that you can position an element from either side. For example, applying top: 0 will align the top of the positioned element with the top of its containing block. Applying bottom: 100%, on the other hand, will align the bottom of the positioned element with the top of its containing block. This can make a design more robust. If you were to try to emulate the same alignment using top, you would have to guess how tall the positioned element is to make the top and bottom line up. Such guesses will frequently break with changes in font size. This technique is especially useful for making folder tab designs.

If you do not define top or bottom (or right or left for horizontal positioning), the element should stay where it is on the page, just not take up room. This could be useful for simulating overstrikes, where multiple letters are printed in the same place. Using negative margins, you can also use this to place footnote symbols to the left of a footnote, for example.

Using margins is a powerful tool with absolute positioning. With a negative margin, you can avoid touching the basic position of the element, but use the margins to move it around, which then keeps the element tied to the place that it would normally appear in the page. This can be extremely useful for things such as CSS tooltips that appear directly next to the element. It can also help dealing with dimensions that combine units, such as positioning a dropdown menu 10em - 1px down the page.


Relative positioning

Relative positioning does two things. First, it lets you move the positioned element without changing how anything around it is placed. A relatively positioned element is laid out on the page as if it were a static element. Then, if you define top, right, bottom or left, it takes the element's presentation (borders, background colors, and content inside of it) and moves it by that amount in that direction, without changing the space the content took up as a static element. It's almost as if you lay out the page, then cut out the relative element with an X-Acto blade and moved it around.

The nice thing about this is it provides a fourth dimension of movement for the element, along with margins, border and padding. (It doesn't change the element's width or height, though -- see the third paragraph in the relative positioning specs.) It can also provide some interesting visual effects by overlaying content over other content and leaving space behind. But, this isn't usually why to apply relative positioning.

Containing blocks: Using positioning to change coordinate systems

The primary reason to use relative positioning is to change the coordinate system used by absolutely positioned elements. Relative, absolute, and fixed elements define new containing blocks for absolute elements[3]. When an absolute element is inside of one of these containing blocks, the top, right, bottom and left properties are no longer based upon the page. Instead, they are based upon the dimensions of this new block.

This can be extremely useful for things such as creating absolutely positioned HTML dropdowns within a form. Since the user can change their font size and window width, you'll never know for sure where the dropdown will appear on the page. But if you wrap the dropdown element in a relatively positioned element that is inside the content, the relatively positioned element will flow with the content and take the dropdown with it, no matter where the relative element lies on the page.

Floating

Floating lets you keep track of where you are in the page, while taking content out of the flow. On the one hand, it is vertically tied to the area on the page where it was defined. On the other hand, it lets block-level elements flow right underneath it as if it weren't there. The inline content of the underlying block-level elements (text, etc.) is pushed over by the float, but the box itself slides underneath the float as if the float weren't there, unless styled to do otherwise.

Floating is a very flexible, and very complicated, design tool. At its simplest, you can use it to float callout boxes in your content, like those pull quotes you see in big type in magazines. At its most complex, you can make multi-level dropdown menus and multi-column layouts.

Although the rules about how floats work are pretty complex, most designs use these basic properties of floats:

  1. An element floated left (or right) will slide as far as it can to the left (or right) within its containing block, as long as that container is wide enough to hold it. (In this case, the containing block is whatever block element the float is defined in.) If there isn't room, it will slide down the page until it finds room to fit horizontally in its container.
  2. For two left-floated boxes, the edge of the right margin for the first box must be to the left of the left margin for the second box. (Same type of thing for right-floated items.) In other words, normally floats won't overlap without applying some negative margin between them.
  3. If a floated element isn't assigned an explicit width, it will be as wide as the content within it.

With these properties, you can do lots of things.

Multi-column layouts

Many multi-column layouts use floats. Since a floated element is shifted to the side of the page, other content can slide up against it. If you just float one column, then any content that continues below the floated element will slide back underneath the float. If every column is in a floated element, though, all of the content will flow down the page within its own column, because the floats won't overlap and the content will stay in its own floating container.

If you want to create a footer that will always stay below all of the content, either use the clear property to make it fall below the floats, or you can float it, too, and give it a width: 100% property. Since floats will go down the page until they find room to fit among the other floated elements, a 100%-wide floating element will always clear other floated elements.

Some of the more advanced multi-column layouts use negative margins to move content around. This works because of property 2 above. As long as the edge of one margin doesn't go beyond the margin of the next box that is facing it, you're good. Now, the fact that, say, the edge of the left margin is to the right of the content area, because it has a huge negative left margin, is besides the point. Most "any-order" layouts take advantage of this.

Tabs

Tabbed navigation is typically created using lists, and making the list items inline elements instead of list-item elements. But what if you want to do designs that use block-level concepts instead of inline-level concepts? Float them.

When a element is floated, it becomes a block-level element (or a table-level element, if it's a table). Assuming that your navigation items are short, you can float them all. Because of property 3, the blocks will only be as long as they need to be to display the content. Because of property 1, they will all slide next to each other (assuming they fit on the line). So you end up with a set of block-level elements that sit side-by-side, instead of atop each other.

Because floats slide all the way to the left or right, you will probably want to put the tabs inside another block-level element that has some margin or positioning on it.

A final note on floats and formatting contexts

Formatting contexts are places in which content is laid out, such as the entire page, a table cell, etc. They interact with floats in two important ways:

  • As long as the formatting context's height isn't specifically defined, floats stay inside the formatting context they're defined in.[4] This can be useful for keeping a float from poking out the bottom of its container.
  • Other block elements will flow around the float (instead of sliding underneath it), if those elements create their own formatting contexts.[5]

These two properties can be useful for making floats clear other elements without additional clearing elements.

For more information on formatting contexts, see the page about it.

Fixed positioning

Fixed positioning is a lot like absolute positioning. Instead of basing the fixed element's dimensions on its containing block, though, fixed elements base their dimensions on the viewport -- the window or printed page. This is quite useful for menus that should always stay onscreen. Unfortunately, it tends to be quite processor intensive, which could slow down scrolling of pages on less powerful computers. It is also not supported by Internet Explorer, but there are workarounds for that.

Positioning attribute Positioning method
Static Absolute Relative Float Fixed
Uses the surrounding content as the basis for its positioning Yes No Yes Yes No
Impacts the layout of surrounding content Yes No Yes Inline content and formatting contexts only No
Defines coordinates for absolute elements No Yes Yes No Yes
Defines the boundaries for how floats slide No Yes No Yes Yes
Design element most suited for this method Standard content, simple single-line navigation Drop-down/Flyout menus and top-of-page navigation/utilities Anchor points for absolute elements Columns, top-of-page navigation Ever-present side navigation, top navigation

Using positioning for design elements

Now that we have the positioning ideas in place, how do we combine them to create different design elements? We've talked about them a bit above, but here's a list that emphasizes the design elements and the positioning used to create them:

Multi-column layouts

Floating is the standard method for creating multi-column layouts. See Float Layouts for some options. Absolute positioning could be used for side columns, but only if they will always be shorter than the main content column. See Absolute Layouts for some examples using absolute positioning.

Vertical navigation

Vertical/side navigation is typically done by placing a statically positioned list inside of a floated or absolutely positioned column, then turning off the bullets and changing the margins/padding on the list items.

Horizontal navigation

Horizontal navigation is usually done in one of two ways:

Inline statically positioned elements. Typically the list items in a statically positioned list are turned into inline elements. Then the links and list items are styled using background colors and borders to create the desired effect. This works as long as inline styling works for you. If not, then floating may be the way to go.

Floated elements. If you want to use block-level styling on your horizontal navigation, then floating is the way to go. In this case, the list items are floated, all in the same direction, so that they pile up next to each other on a line. When side borders are applied to make the individual elements look like a table, negative margin can be applied to one of the side edges to overlap the doubled-up borders. Typically the floated elements are contained in something that pushes them off of the edge of the screen, such as an absolute element or another element with a margin.

Drop-down menus

Typically, the drop-down menus themselves are absolutely positioned. The elements they drop from are relatively or absolutely positioned, so that the drop-down portion can be properly aligned with the content or the entire page. Frequently you can use top: 100% on the drop-down portion, to align the top of the drop-down to the bottom of the anchor.

When making a horizontal navigation with drop-down components, you can combine floating, relative positioning, and absolute positioning, so that each floated item of horizontal navigation provides an anchor box for the drop-downs, like so:

<style type="text/css">
    #nav {
        display: block;
        list-style-type: none;
        position: absolute; /* create the context for the floated horizontal navigation */
        top: ''yyy''; /* stick them somewhere on the page */
        left: ''xxx'';
    }

    #nav li {
        float: left; /* create the block for the tab portion the navigation */
        position: relative; /* define the anchor point for the drop-down */
        padding: 0;
        margin: 0;
    }

    #nav ul {
        display: block;
        list-style-type: none;
        position: absolute; /* define this as the drop-down portion of the tab */
        visibility: hidden; /* hide it */
        top: 100%; /* push the top of the drop-down to the bottom of the anchor */
        left: 0;
        width: 15em; /* define a width for the drop-downs */
        padding: 0;
        margin: 0;
    }

    #nav li:hover ul {
        visibility: visible; /* show the drop-down when hovering over the anchor */
    }

    /* by letting the LI's in the drop-downs float, the surrounding UL won't take
       up any vertical room. Floats are pulled out of the flow and only impact
       inline-level elements. Since all of the inline content is inside of floats,
       the surrounding blocks shrink up and take no room. */
    #nav ul li {
        display: block;
        width: 100%; /* make sure the floats are wide enough that they always wrap */
        padding: 0;
        margin: 0;
    }

    #nav a {
        display: block;
        padding: .5em;
        border: 1px solid black;
    }
</style>

<ul id="nav">
    <li><a href="tab1.html">Tab 1</a>
        <ul>
            <li><a href="section1.1.html">Drop-down item 1.1</a></li>
            <li><a href="section1.2.html">Drop-down item 1.2</a></li>
        </ul>
    </li>
    <li><a href="tab2.html">Tab 2</a>
        <ul>
            <li><a href="section2.1.html">Drop-down item 2.1</a></li>
            <li><a href="section2.2.html">Drop-down item 2.2</a></li>
        </ul>
    </li>
    <li><a href="tab3.html">Tab 3</a>
        <ul>
            <li><a href="section3.1.html">Drop-down item 3.1</a></li>
            <li><a href="section3.2.html">Drop-down item 3.2</a></li>
        </ul>
    </li>
</ul>
Personal tools