My JavaScript book is out! Don't miss the opportunity to upgrade your beginner or average dev skills.

Monday, September 21, 2009

CSS Position Fixed Solution

Who does not know CSS 2.1? ... silence (maybe) ...
Good, so who does not know the CSS 2.1 position property? ... silence (still maybe though) ...

Excellent! Finally, who would like to use in a lightweight, cross-browser, unobtrusive way, without JavaScript dependencies, the property fixed? ... silence again, but this time I can spot a different expression in your face ...


Common Browsers With position:fixed Support

  • Chrome
  • Firefox
  • Internet Explorer 7 and 8 but NOT in quirks mode
  • Opera
  • Safari


Common Browsers WithOut position:fixed Support

  • Internet Explorer 6
  • Internet Explorer 7 and 8 in quirks mode
  • WebKit for Android
  • WebKit for iPhone


To Quirks Or Not To Quirks

For backward compatibility reasons IE let developers choose between two box models ... Our loved bloody 64 years* old browser Internet Explorer 6 has never supported such property while both Internet Explorer 7 and 8 do nt support it if we are in quirks mode, a modality tendentiously dead thanks to new simple HTML 5 doctype declaration: <!DOCTYPE html>.
To solve this issue I have created a dedicated file to include via conditional comments which includes a set of "never before that useful" expressions.

Why Expressions

CSS expressions are compatible, so far, only with Microsoft IE browser and they are totally alien for both other browsers and developers. The reason I am saying that is because they are completely unpredictable: it is not possible to easily understand or to predict when expressions will be executed, where, and how!
Technically speaking, being expressions dedicated for CSS hacks, their executions will be performed at least every time the element is somehow involved, and to make it involved, we need to touch some property in order to make expression useful (in this solution case the property offsetHeight of the current node).

The Direct Example

Here we have two pages: the standard or strict mode and the quirks one.
As you can test via your favorite browsers, there are always 5 elements in that page, a top div, a center one, a bottom one, and two divs one left and one right, above and over the center one.

How Does It Work

It is very simple, consider these CSS classes:

/** A WebReflection Solution */
.position-fixed-top {
position:fixed !important;
top: 0;
}
.position-fixed-center {
position:fixed !important;
top: 50%;
}
.position-fixed-bottom {
position:fixed !important;
bottom:0;
}

Hopefully choose name are semantic enough, so it's quite clear that these classes aim is only to position elements, and nothing else, in order to be able to add other classes for whatever other property, zIndex if necessary included.
Choose classes are about most common usage of fixed elements in a page, top, center, or bottom, and adjusting positions or margins it is really simple to put the element in whatever part of the page starting from the bottom, from the top, or the left.
To let the magic be in Internet Explorer 6 and others in quirks mode, these classes are completely replaced, as you can read in IE dedicated file.
Being the IE solution based on CSS expressions, there should not be anything better or quicker than that, render time and call speaking, same should be for memory leaks, timers, and whatever strategy we have adopted 'till now (but of course if there is something better please share!).

Android & iPhone - Not Worth It

These mobile devices implement a stunning browser as dedicated WebKit is, able to render faster than IE8, for example, my last Liquid FX, based on 1 image, and one div, that's it! (congrats IE8 for stretched images rendering time! 7, 6, and 5.5. are much better) ... uh, wait, it's not about IE ...
Android and iPhone have both a great CSS 2.1 support, and even some CSS 3. Unfortunately the position fixed does not work as expected. To fix it I have tried different scripts failing each time. The reason is quite simple: both Android and iPhone block timers or render during scroll, so the effect is that divs move with the scrolled page and only after, eventually, divs come back in the expected position. This is against position fixed idea, and having a truly small screen we should ask our self if it makes sense to cover precious pixels with something fixed there.
It does not matter, as soon as I'll be able to test an iPhone I will continue to optimize my script in order to make the position fixed property usable somehow with mobile devices as well ( center right or center left could be interesting, bottom or top bar quite intrusive for user and/or zooming features ).

How To Implement My Solution

It's simple, if we are in a quirks page, we should include the CSS hacked file after the normal one, and for every IE:

<link rel="stylesheet" type="text/css" href="position-fixed.css" />
<!--[if IE]>
<link rel="stylesheet" type="text/css" href="position-fixed.IE.css" />
<![endif]-->

While for every standard or strict web page we can include the hack only for IE less than version 7:

<link rel="stylesheet" type="text/css" href="position-fixed.css" />
<!--[if lt IE 7]>
<link rel="stylesheet" type="text/css" href="position-fixed.IE.css?444" />
<![endif]-->

I can spot a new expression in your face, isn't it?


* if we multiply per 7 dogs age, I think it is reasonable to say that in IT each year could be multiplied for 8

17 comments:

MIvan said...

I have seen many sollutions on the web for this problem, but this was the right one.
Only one little addition, to stop the jumpy effect: put
background: url(foo) fixed;
into body{}
Thx!

Fabrizio Calderan said...

I published a solution several months ago in http://css.html.it/articoli/leggi/3074/position-fixed-performante-su-ie6/

I wrote it in italian, but the available code for download should be clear to everyone. And it includes the MIvan suggestion.

Bye

Andrea Giammarchi said...

Fabrizio your one is just another solution that does not bring anything different and I am not sure it is going to work in quirks mode.

CSS expressions or a behavior used for CSS purpose does not make any difference, you are using code to manipulate CSS.

Your htc file could require special settings in the web server, some webserver won't work as expected with unrecognized file and this could cause problems.

My code is so simple that it does not require effort to be maintained, but the point is that it simply works, with semantic classes for common positions, and it is lighter than your code.

Finally, there is no reason to say: If you use expressions coordinates will be hard coded, as you can spot, there is nothing hard coded here.

I have to say, in any case, I did not know that article, but now that I do, I will continue to use my solution but thanks in any case for the alternative, just consider that these things are for IE6 and htc or not, it is slow by default :)

Regards

Andrea Giammarchi said...

P.S. moreover ... CSS hacks are a bad thing, not less than expressions, conditional comments are an acceptable, suggested, solution, for IE related stuff.

Anonymous said...

Great solution, the best I've seen and easy to port to any page. Thanks, I'm glad to have this in my coding toolbox

G. Ludwig

Andrea Giammarchi said...

@MIvan IE will try to download "foo" in that case, probably this is better:
body {
background: url(data:null) fixed;
}

Andrea Giammarchi said...

@MIvan IE will try to download "foo" in that case, probably this is better:
body {
background: url(data:null) fixed;
}

Sean said...

I'm not sure what you meant by "without Javascript dependencies", but this solution won't work if Javascript is disabled.

Also, I'm pretty sure Dean Edwards IE7 solved this one about five years ago.

Thanks for the tip about Android, etc. I can easily imagine those mobile browsers making web-dev really frustrating. (I mean, even more than it was.)

Andrea Giammarchi said...

shogun70 without JavaScript dependencies means no needs for JavaScript manipulation.

JavaScript is required only in IE6 expressions, IE7 if not in quirks mode is already compatible with position fixed.

I am sure Dean, as me and everybody else, solved the problem via JavaScript ages ago, not big deal, but you cannot find similar, lightweight, cross-browser solutions like this one.

If you can find something better please share. Thanks

Sean said...

Dean Edwards solution uses CSS expressions. The Javascript merely rewrites the stylesheet.

Andrea Giammarchi said...

Dean IE7 is not a couple of CSS file for few bytes.
You are assuming I did not know Dean Edwards solution which is false.
This is a solution which is simple, lightweight, cross-browser, and does not use JavaScript in the meaning there is no JavaScript inclusion at all neither a global pollution of variables or a namespace.
If you need Dean's IE7 use it, what I have provided here is something different not present in Dean IE7

Regards

Anonymous said...

Thanks for posting this! I have to use quirks mode - and this is the only fix I found to properly emulate 'position:fixed' in quirks mode in IE 7 .

Emlyn said...

So there's currently no solution to a position:fixed element in an iPhone/mobile browser?

A client brought this nasty little fact to my attention and I've been hunting for a solution to a bottom-positioned footer bar that is floating in the middle of her iPhone screen!

Any hacks you didn't try yet but think might work?

Andrea Giammarchi said...

well, there may be some valid hack, the point here is that JavaScript cannot solve this problem since it's not executed while we are scrolling the page but a scrolling div width 100% and height N pixels with another one after as bottom div, plus some trick over touchmove could potentially solve Android and iPhone problem (handling manually the scrollable div)

kannan said...

awesome dude, thank you verymuch... its more helpful for me

Robot Peter said...

For android devices, i tested something I found on this page
http://kentbrewster.com/android-scroller/
I think it has to do with the meta tag specification; the css remains- position:fixed, bottom:0 or top:0 or top:50%, ... depending on where you want to fix it

Anonymous said...

Thank you so much for this. Ridiculous that we should have to implement a solution like this in this day and age, but a malformed doctype out of our control left us with no other position:fixed solutions working. Yours does. Might be an old post, but thank you all the same.