I've always found CSS positioning with both float and position: absolute/relative hard to work with. I want to introduce to you an alternative way borrowed from the World of Warcraft Interface: Anchors.

Anchor

The concept is extremely simple. You can tell where you want the element to be, relative to another. For example, top left of this blog's main content is 10px right relative to the top right of the menu.

<frame name="Content">
  <anchor point="TOP LEFT" relativeTo="Menu" relativePoint="TOP RIGHT" x="10" />
</frame>
  • Allowed points:
       TOP LEFT ,  TOP   , TOP RIGHT
           LEFT , CENTER , RIGHT
    BOTTOM LEFT , BOTTOM , BOTTOM RIGHT
  • Default Values:
    • point, relativePoint: TOP LEFT.
    • relativeTo: Parent of the element.
    • x, y: 0.

Demo

I've made a quick implementation of this behavior in HTML using data-attribute. Check the Javascript tab to see the 35 lines of CoffeeScript that makes the following code work:

<!-- In order to put the sidebar centered at the right of the frame:
  Sidebar.left = Frame.right                                          -->
<div id="sidebar" data-anchor="left, #frame, right"></div>
 
<!-- In order to put the chat at the top right of the screen:
  Chat.topRight = HTML.topRight + {x: -10, y: 10}                       -->
<div id="chat" data-anchor="top right, html, top right, -10, 10"></div>

Limitations

Static

The current code works well for static elements. As there isn't any event for DOM move/resize, the position will not be updated if anything moves ๐Ÿ™

It might be possible to achieve the same effect by setting properly the position: absolute/relative and top/bottom/right/left CSS properties. I'd be really interested to know if you try to tackle this challenge ๐Ÿ™‚

CSS Attribute

It would be more semantically correct to add an anchor CSS attribute instead of an HTML data attribute. However, it's not possible to access the value of a custom CSS property.

#sidebar {
  anchor: bottom left #frame top right 10px 0;
}

Multiple Anchors

World of Warcraft supports multiple anchors. For example if you anchor both the left and right sides, then the width of the element is going to be updated accordingly.

I came across a CSS problem, text-align: justify does not work with only one line.

Justify behavior

The reason is because it has been designed with paragraphs in mind. It justifies all the lines but the last one.

Normal Justify

Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat laboris.

Full Justify

Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat laboris.

Solution

The solution (given by cam) is to put an extra tag at the end of the paragraph that will be big enough to create a new line. Fortunately, it is possible to do it without affecting the markup using :after. We are going to put an empty tag as big as the line.

.fulljustify {
  text-align: justify;
}
.fulljustify:after {
  content: "";
  display: inline-block;
  width: 100%;
}

Now you can add class="fulljustify" in order to justify your one-line divs ๐Ÿ™‚

This is a one-liner. Please justify!

CSS development is a hard land where you have to struggle with many browser incompatibilities and not so easy to use structures. Here are two extremely useful techniques that allow you to get around common float problems.

List of items without floats

Problem

It is common to display a list of items that flow horizontally. Common examples are tabs or cloud tags. A common way to write it is to use the float property.

<style>
  li { float: left; }
</style>
<ul>
  <li>One</li>
  <li>Two</li>
  <li>Three</li>
</ul>

However, you are going to struggle with the way floating elements flow in the document. You have to clear them, you will have strange behaviors with multiple floats ...

Technique

There is a better way to do it: display: inline-block;. The element will behave inline (as a span) when being positioned in the flow and as a block when styling it. Exactly what you want.

The code is nearly the same, but the float is now gone!

<style>
  li { display: inline-block; }
</style>
<ul>
  <li>One</li>
  <li>Two</li>
  <li>Three</li>
</ul>

However, this code does not work in ie7 (and of course ie6). But ... There is a simple trick to make it work! Every time you do a display: inline-block, just add the two associated lines. The magic is explained by Ryan Doherty from Mozilla.

li {
  display: inline-block;
/* The following 2 lines do the magic */
  zoom: 1;
  *display: inline;
}

You can read more about the zoom property and its strangeness on the On Having Layout article.

Benefits

  • No more floats and all the problems involved
  • Cross browser (even ie6)
  • You can now center elements using text-align

Demo

  • One
  • Two
  • Three
  • Four
  • Five

No more clear to get around floating elements

Problem

When working with floating elements, you are probably going to do something like this:

<div>
  <div style="float: left;">Left Menu</div>
  <div style="float: left;">Another Menu</div>
  <div style="float: right;">Content</div>
  <br style="clear: both;" />
</div>

The problem is you have to use a <br /> which takes vertical space, completely destroy your padding/margin organization ...

Technique

There is one easy technique described by PPK that is solving all the problems and has no side effect!

<div style="width: 100%; overflow: auto;">
  <div style="float: left;">Left Menu</div>
  <div style="float: left;">Another Menu</div>
  <div style="float: right;">Content</div>
</div>

The trick is to add width: 100%; overflow: auto; to the parent box and it just works! The parent box now wraps around all the floating elements and you can properly style it. It works will all browsers, even with ie6.

Demo