Faux Absolute Positioning
Issue № 261

Faux Absolute Positioning

There are two popular approaches to positioning with CSS: float and absolute positioning. Both approaches have their pros and cons. My teammates and I have developed a new positioning approach that gives us the best of both worlds. After quite a bit of experimenting and testing, it’s time to share the technique with the rest of the world and see how we can work together to improve it. I’m calling it “faux absolute positioning” after the faux columns technique that simulates the presence of a column.

Article Continues Below

Why do we need another CSS layout technique?#section2

Many website designs are based on a columnar layout with a header and footer.  With absolutely positioned layouts, it is almost impossible to position the footer if the columns can grow vertically. With floated layouts, unexpected content changes can cause entire columns to wrap (“float drop”), as described by Shaun Inman in Clearance. This is undesirable and hard to control in Internet Explorer because of IE’s problematic treatment of width.

Our use case was even more complex: my team was developing a web-based WYSIWYG form generator that allows the user to drag items to arbitrary locations on a canvas.  We needed to let our users create beautiful forms that didn’t use overly static layouts and to let them align columns as needed.

For example, let’s assume we want a form that puts the postal code and city fields on the same line because they are semantically connected. To accomplish this, we tried using floated positioning inspired by the Holy Grail technique. Using this method, we needed to adjust the width, borders, margins, and/or padding of the postal code field to pin the city field to a fixed horizontal position. That was a problem because if the width of the postal code field needed adjusting, or if we wanted to adjust the amount of whitespace between fields, the city field would need to move as well. The more elements on a page—the more cells in your grid—the more tedious this kind of adjustment becomes. Additionally, the positioning is sensitive to the slightest change in a number of parameters, which makes it nigh impossible to control in case of dynamic form items.

Next, we tried using absolute positioning. This gave us much more control over the positioning of the items and is robust. But absolutely positioned elements have no height, and that caused the containing element (the canvas) to collapse. This made it hard to position content without making everything absolutely positioned—which is impossible to achieve with dynamic content.

A different approach#section3

Finally, we tried a solution based on finding a way to calculate the left offset from a fixed position, as opposed to calculating it from the right edge of the preceding element. We managed to do this using a combination of position: relative, left: 100% and a negative margin-left.

Our method starts by building a grid of lines and items. We can place any number of items on a line and any number of lines in the containing element:

<div id="canvas">
  <div class="line">
    <div class="item" id="item1">
      <div class="sap-content">content here</div>
    </div>
  </div>
</div>

…and so on. Every item has an extra sap-content div with several purposes:

  • it prevents the redraw bug in IE6,
  • it gives us extra flexibility to add padding (example below), and
  • it lets us play with position: overflow (without breaking the grid!).

The generic CSS applied to these elements is as follows:

.line {
  float: left;
  width: 100%;
  display: block;
  position: relative;
}.item {
  position: relative;
  float: left;
  left: 100%;
}

To position a particular item, all we need to do is give it a negative margin-left and a width. For example:

#item1 {
  margin-left: -100%;
  width: 30%;
}

With some extra styling, for demonstration purposes, it looks like this:

Example of Faux Absolute Positioning in action.

The generic CSS positions every item at the right side of the canvas, with each item’s width based on its content and all items floated in their HTML source order. The margin-left is now offset from the right side of the canvas instead of from the element to its left.

Advantages#section4

With faux absolute positioning, we can align every item to a predefined position on the grid (as with absolute positioning) but items still affect the normal flow and—thanks to clear—have many of the same advantages as normal-flow elements. Every row in the grid will always have height dependent on the content or as defined in CSS, and will always take up 100% of the width, no matter how many columns are defined in the row. Furthermore, we can avoid using cumbersome margins or padding to adjust the amount of whitespace between elements—which is a plus, since those techniques almost always require us to use IE6-specific hacks to compensate for the browser’s box model.

Another advantage of the technique is that it mitigates much of the fragility of floats. When the content of a floated box is wider than the box itself, it pushes the next box to the right (and by consequence, the box often drops down). With faux absolute positioning, the box to the right stays in place, no matter what. The content of the boxes may overlap (depending on other variables such as overflow: hidden) but that’s all—and in our view, it’s better to risk overlap than risk breaking the whole layout.

Honestly, I was a bit surprised that the technique worked so well. It uses valid HTML 4.01 and CSS 2.1, and negative left margins are widely implemented in browsers. And there’s more good news: it works with fixed and liquid designs, it can be combined with equal height columns (though the issues with this solution remain), and there is the possibility of combining fixed-width and flexible-width columns (see the example below). It is even possible to use faux absolute positioning recursively, e.g., use a positioned item as the container for new lines and items.

Downsides#section5

Faux absolute positioning is very much inspired by and intended for grid-based design and is more rewarding with more complex layouts. If you have a two-column fixed-width design, this may not be your technique of choice.

Additionally, faux absolute positioning will not work for every situation. If you want to align elements on the left, you cannot use a unit that is different from the unit in which the width of the canvas is defined, because you cannot calculate the offset. For example, if you have a canvas width: 800px and want a left offset of 2em for your item you cannot calculate the margin-left because you never know how many ems fit in 800 pixels.

And since it is a new technique that hasn’t been tested by thousands of users, it should still be considered experimental, as you may see unexpected results in your actual combination of markup, CSS, and browser.

One remaining issue: when an element larger than the canvas precedes other elements in the HTML source, the trailing elements on the same line will be pushed to the right by an amount equal to the difference in width between the the first element and the canvas.

Examples#section6

The first example is a three-column liquid layout with fixed side columns, like the Holy Grail. I have implemented this layout as a template for Drupal, a popular open source CMS. There are a few things to note:

  1. The left and right columns have widths in pixels. Therefore, we cannot calculate margin-left for the main content, because we don’t know the width of the canvas or the width of the left column as a percentage of the canvas. The solution is similar to the Holy Grail: position the main content with margin-left: -100% and width: 100% and add padding to provide the necessary space for the columns.
  2. Left, main, and right columns are rendered at the same hierarchical level, so we may need something like z-index: 100 on the columns.
  3. Padding for the left and right columns is added to the extra div.sap-content; this keeps our math simple while affording us a great deal of flexibility.

The second example is a five-column liquid design in which canvas, lines, and items are all sized in percentages. The addition of images, borders and paddings have no effect on the overall positioning, even for images that are larger than the containing element, as is demonstrated with the old map of Maastricht in the example.

No hacks required!#section7

Our approach requires no hacks and it works with all modern browsers (Safari, Opera, Firefox, IE7) as well as IE6 and even IE5.5/Win. It does not work in IE5/Mac, but since this product has been discontinued, it is not on our priority list.

The approach is also very stable, since elements grow vertically if necessary, and the layout does not break when an image is wider than the element, for example. The positioning of items is independent from the source order in HTML.

I am quite enthusiastic about this approach and see many opportunities for it. Feel free to try, experiment and post your comments.

About the Author

Eric Sol

Eric Sol is founder of a small software firm based in beautiful Maastricht, The Netherlands. He has held several positions in Dutch higher education, both in ICT and policy making. He started his journey into CSS in October, 2006. Besides having a family he likes cycling and listening to his collection of vinyl and CDs.

125 Reader Comments

  1. Robert, i can help explain the principle if you want. I can see how it can be confusing to get your head around, but once you’ve got it, it really is very useful.

    I tried to find an email address through your website, but couldnt. Let me know if you need a hand.

  2. I love this technique, although I know there are some arguments against it (google faux positioning). In fact I love it so much that the new base theme for Drupal I’m making is based on this technique and it works great! In the first website I did with this base theme I’m having a problem, when I added a table of contents that uses same pahe links, whenever I clicked on a section all of the content in the main div that came before it, dissappeared. If I give overflow:scoll just to the main div, I get a scrollbar in the div and I can see the content scrolling up. This is pretty much a deal braker for that particular theme I’m building because I really need table of contents because of the amount of content the pages in the site has. Is there any way to be able to use this technique with table of contents?

  3. I can confirm that Rafael is correct with the fact that in IE6 a background image on one of the main ‘columns’ (item) will throw off the layout completely. Mousing over a link snaps the columns back to where they should be, but obviously that’s no solution.

    For now the best solution I can find is to put the background image on an element within the column/item instead.

    Strangely, using a background _colour_ doesn’t cause the same glitch.

  4. Nice article and interesting technique! Just one minor typo:

    bq. [I]t lets us play with @position: overflow@ (without breaking the grid!).

    My first impulse is always to doubt myself, but I’m sure that’s not a legitimate value for this property! 🙂

  5. from the examples: scales poorly past a certain point. or was this just in the examples?

  6. I have used this to redo the css for a site that went live earlier this year,

    My only problem is I cannot work out how to stop the menu in the left hand column from being displayed. Ive tried

    #sidebar-left.item column, #ddblueblockmenu
    {
    display: none;
    }

    and various combinations but it still gets printed . Any ideas

  7. This is awesome! I just starting fooling around with it and I can already see how efficient this is. Thanks for the article!!!

    J

  8. I really just wanted to make a simple personal site. But the complexity of doing just the simplest of things have such a myriad of choices that I just want to throw my hands up in the air and scream. I thought CSS was to be a universal solution that would enable once and for all the ability for everyone to be on the same level playing surface. But as it turns out, for every solution there is 10 opinions that state the opposite or the same but different approach. I see why even though FrontPage was so hated by so many, that it really made things simple. That is, until we went to Expression versions. I guess at least everyone is in the same but different bucket of confusion. Ultimately, I guess my question is: have we really come that far? Just seems like everyone is just arguing a new subject, but in reality it just the same old stuff – no one agrees on anything. Why has CSS made everything so complex? When its original intent was to simplify. Maybe we should all start from scratch again!

  9. There will be a problem when I add a background-image to that DIV in IE 6. All DIVs that contain a bckground-image will be kept in the right and not in the correct position.

    Do you have any method to solve this bug?

  10. Thank you for publishing this great tip!! I’ve been trying to implement tableless CSS design and this makes it so much easier. Keep the great tips coming!

  11. Thanks for sharing this concept. It is very interesting for me as I used to spent hours fixing some broken css layouts in IE 5 & 6. I will try this layout technic in one of my next projects.

  12. This is a phenomenal technique, but I’ve run into an issue that a few others have mentioned. To reproduce this error, use a background-image on an element with class-name “item” and see how IE6 reacts.

    It appears that this is a “Peek-a-boo bug”:http://www.positioniseverything.net/explorer/peekaboo.html – the element is invisible when you load/reload the page, but suddenly reappears when you resize the browser window.

    I tried to use the “clearfix”:http://www.positioniseverything.net/easyclearing.html approach to no avail and ended up refactoring my layout to make use of the sap-content element for background images.

    Hopefully this extra info will help someone smarter than myself to find a more robust solution.

  13. I’ve been building websites for years and consider myself pretty nifty with CSS, but a method like this just never occurred to me! It looks robust and pretty straight forward and I’ll deffinitely give it a try next time I need to do a reasonably complex layout. Cheers guys!

  14. That’s an awesome job at problem solving…I’ve wondered how to do something similar to this for awhile, because I hate using tables for layouts because they’re slow-loading, and with divs I felt like I was stuck into only creating 2 column-layouts for fear of creating broken layouts if the elements end up growing too much or the padding/margins aren’t quite the same for every browser. Good solution.

  15. I’m very intrigued by this approach, and so far testing it against various browsers has worked fine… except for one IE6 (?) glitch: when using a two-column layout with Faux Absolute Positioning, and IE6 is running on a Virtual PC, the left column frequently (but not always) gets displayed to the far right. For more info see: “Anyone seen image positioning problems with IE6 running on a Virtual PC?” on MSDN IE Web Dev forum…

  16. My IE6 layout problem had already been reported (although apparently not yet completely resolved). I must have accidentally jumped past those posts…

    But knowing that it’s aggravated when running under VPC may shed some light on how someone (smarter than me) might come up with the best work-around.

  17. Nice article, and nice techniques. I haven’t sen this approach before, and I will try it out.

    I’ve been wondering similar things when it comes to multi-column layouts, and I have an idea that I’ve been using that I’d lke to run past you, or anyone else.

    I’ve been using elements with the CSS display: inline-block. In combination with the vertical-align: top; property, I can achieve something very much like two or three table cells sitting next to eachother in a row, since they are sitting on the same text baseline (inline) but can take width properties (block). It’s a nice combination of the two.

    The problem is, if you stick a DIV inside of these spans, the layout will not validate. Since Spans are default inline, is it not allowed to insert a block-level div inside of them. The reason why I use Spans in the first place is that as early as v5, inline-block is supported in IE only on elements that are by default inline. So, spans, anchors, img tags, etc… can be inline-block, but DIVs can not.

    So, the question is, while this is a powerful layout tool, is it off limits since it technically is not allowed? Will the inline-block property eventually go the way of the dodo and cease to be supported?

    Anyone?

  18. Hi Eric!
    I have stumbled upon this technique while looking for a solution to my problem. I am still not sure if/how I can use it. I think you may have had the same issue. The users have a “screen designer” for a form layout. I need to replicate that in the browser. Now it’s done with absolute positioning, and the problem is that the footer, which comes right after the form’s content, now gets placed to the top because of absolutely positioned elements in the form that don’t provide the form with a height. Can I move the footer in it’s place by still positioning the elements inside the form in the same positions the user did? If so, how. I seem to not getting exactly the point.
    Thanks!

Got something to say?

We have turned off comments, but you can see what folks had to say before we did so.

More from ALA

I am a creative.

A List Apart founder and web design OG Zeldman ponders the moments of inspiration, the hours of plodding, and the ultimate mystery at the heart of a creative career.
Career