additions...

...web design...

position: fixed in IE/win…

IE6 (and older versions) doesn't support 'position: fixed' and usually makes a mess out of what it doesn't understand, so many designers avoid using this powerful, W3C-standardized, property. It's a shame, really.

use 'position: fixed' with care…

One should look carefully into all posibilities for failures, before applying 'position: fixed' to foreground-elements – even in browsers that handles it perfectly. The viewport-size at the User end is at best an unknown factor, and the available space may be quite small.

Only relatively small-sized foreground-elements should be designed to take up a fixed space in the viewport. The parts of large, fix-positioned, fixed-size elements that end up outside small viewports will stay out of reach, and there's nothing short of a scrolling-mechanism provided in the design itself that can bring it back into view.

There are 3 demos on this page – in case you have missed them. Those small images are supposed to stay glued to the window, or viewport, somewhere to the right of this column. They should stay there in IE/win too – as long as javascript, and thereby also my IE-expressions, are allowed to work.

CSS for these demos can be found in the page-head, and the elements used are located near the bottom of the source-code. Description and additional information follows...

borrowed and home made solutions…

I have made heavy use of other people's work, and listed known external resources. Thus, anyone can check what's “borrowed” and what's “home made”. Basically, I have put pieces together, mixed them well, added some logic and a few pieces of my own, and made the resulting packages work.

I take no credit for any of this, as I had nothing better to do at the time anyway. Making Internet Explorer work isn't one of my priorities, but since it can be done, then, why not?

Most workarounds for IE/win suffer from weaknesses, and most can only be used for fairly size-limited elements. I may accept the addition of some IE-only garbage in both HTML and CSS in order to get “fixed” working, but then it should better work close to perfection.

I have taken into account that most javascript-based solutions – like IE-expressions – are mode-dependent. So, I have written my IE-expressions to be mode-independent or dual mode, so they will work properly in both Quirks and Strict mode. Other mode-related differences, like fixing box-models and such, are up to each site-developer to fix, as they are the ones who decide on DocType and other variables.

element fixed to top of viewport…

Two basic ingredients are needed for 'fixing' an element nicely to the viewport: an IE-expression and a speed fix.

dual mode IE-expression:
* html div#fixme {position: absolute;
top:expression(eval(document.compatMode &&
document.compatMode=='CSS1Compat') ?
documentElement.scrollTop : document.body.scrollTop);}

IE/win will act a bit sluggish when long pages are scrolled with such a “fixed” element in place. Luckily, that sluggishness can be overcome by applying the only 'position: fixed' IE/win understands – a background on body.

a 'speed fix':

a background-image on body with 'background-attachment: fixed' will do...

* html,* html body{
    background: #fff url(image.jpg) fixed;
  }

...or, if no fixed background is wanted/needed, a link to a non-existing file with 'background-attachment: fixed' will work as well.

* html,* html body{
    background: #fff url(foo) fixed;
  }

Note: this 'speed fix' is easy to mess up with other styles – making it useless. I'll look into the details later, and add them here.

Update 17.sep.2006: Since IE6 also needs a fixed background-attachment on the html element to prevent the jerkiness when in standard mode, I've updated the 'speed fix' alternatives above to work regardless of mode.

There we have it, IE6 (and IE5.0, 5.5) will “fix” that div#fixme to top of the browser-window. Time to move on.

element fixed to bottom of viewport…

We start at the top of viewport, and add in height of viewport. That will bring our “fixed” element at the very bottom of the viewport.

dual mode IE-expression:
* html div#fixme-bottom {position: absolute;
top:expression(eval(document.compatMode &&
document.compatMode=='CSS1Compat') ?
documentElement.scrollTop
+(documentElement.clientHeight-this.clientHeight) 
: document.body.scrollTop
+(document.body.clientHeight-this.clientHeight));}

This IE-expression might be useful for positioning a footer. I've got one on the Table of Contents for this site-section.

element fixed to middle of viewport…

Again, we start at top of viewport, and add in height of viewport divided by 2. That should bring us right in the middle of viewport – and it does.

dual mode IE-expression:
* html div#fixme-middle {position: absolute;
top:expression(eval(document.compatMode &&
document.compatMode=='CSS1Compat') ?
documentElement.scrollTop
+((documentElement.clientHeight-this.clientHeight)/2 )
: document.body.scrollTop
+((document.body.clientHeight-this.clientHeight)/2));}

It should be obvious that the divider can be any number equal to or larger than 1, so dividing by 4 to simulate 'top: 25%', or dividing by 1.33 to simulate 'top: 75%' or 'bottom: 25%' will work. Test, and compare with the good browsers.

“fixed” horizontally:

We can of course use complex IE-expressions for exact horizontal positioning also. If we want near-perfect simulation of real 'position: fixed' then we have to make the horizontal position “fixed” too. Here are the basic versions exemplified.

simulating left: 100px...
left:expression(eval(document.compatMode &&
document.compatMode=='CSS1Compat') ?
documentElement.scrollLeft + 100 
: document.body.scrollLeft + 100);
simulating right: 200px...
left:expression(eval(document.compatMode &&
document.compatMode=='CSS1Compat') ?
documentElement.scrollLeft 
+ (document.body.clientWidth - 200 ) 
: document.body.scrollLeft 
+ (document.body.offsetWidth - 200 ));
simulating left: 75% / right: 25%...
left:expression(eval(document.compatMode &&
document.compatMode=='CSS1Compat') ?
documentElement.scrollLeft 
+ (document.body.clientWidth /1.37 ) 
: document.body.scrollLeft 
+ (document.body.offsetWidth /1.395 ));

The effect becomes most obvious if you make the window narrower than this page's min-width (simulated by another IE-expression), and scroll to the right. The “fixed” demo-image in the middle will stay horizontally “fixed” to the viewport in IE6, just like in all the good browsers. The demo-images on top and bottom on the other hand, will follow the page since they are not “fixed” horizontally.

Whether or not to add horizontal “fix” to a vertically “fixed” element, depends on the effect one wants to achieve and the degree of “exact simulation” one wants. I haven't used horizontal “fix” much myself, but it does add to the illusion that IE6 can handle 'position: fixed'.

An added advantage of the added horizontal “fix” can be observed in IE in Quirks mode – as on this very page. There's a slight horizontal positioning-error for the demo images on top and bottom (which aren't horizontally “fixed”) when page is first loaded or reloaded, followed by a slight horizontal jump once the page is scrolled ever so slightly. The demo-image in the middle (which is horizontally “fixed”) is positioned correct and perfectly stable every time.

offset “fixed” relative to its container:

Unlike the real 'position: fixed', this workaround allow us to offset the “fixed” position by making the “fixed” element stay relative to (one of) its containers. That's how 'position: absolute' works, but the IE-expression will keep the “fixed” element steady in relation to top of the window anyway.

Note: one should remember this offset-effect when elements are organized in the source-code (HTML). We can not always pick up an element from anywhere and position it “fixed” in IE/win. Our “fixed” element may unintentionally end up with offset relative to a container-element.

how to intentionally offset a “fixed” element in IE/win:
* html #content {
position: relative;
}
<div id="content">
<div id="fixme"> some fixed content </div>
</div>

This will work as long as the relative positioned container and the entire “fixed” element is visible in the window. If parts of the “fixed” element goes outside the window, then the confused calculations in the IE-expression will result in some nasty side-effects, like endless scrolling.

offset element relative to its “fixed” position…

For completeness: margins can be used to offset any element from its fixed position – in all browsers. So if we have added a complete simulation for 'position: fixed' for an element in IE6, then we can also add push and pull margins and expect them to work.

large elements “fixed” to viewport…

We rarely ever have complete control over the size of the visitor's viewport. Thus, using the solution above for large elements will run into those side-effects, like endless scrolling. This is where some heavy cheating comes into play.

First, I nest an extra div inside the “fixed” element. Then I zero out the dimension on the “fixed” element, and move all the stuff I want to present onto the “removed float” nested inside it and make that float overflow its non-dimensional “fixed” container. Then I apply the IE-expression, and add “positioning-offset” for the non-dimensional “fixed” element.

using a non-dimensional a.p. element for positioning:
* html div#fixme {
position: absolute; 
height: 0; 
width: 0;
}
using a float that takes up no area, to avoid the endless scroll on small windows:
* html div#fixme div  {
height: auto; 
width: 80%; 
position: relative; 
margin: 0 -10000px -10000px 0;
float: left; }

This “trick” utilizes a nasty float-bug in IE/win. See: removed float for details.

adding the expression for “fixed” to top of viewport
* html div#fixme {
top:expression(eval(document.compatMode &&
document.compatMode=='CSS1Compat') ?
documentElement.scrollTop : document.body.scrollTop);}
adding a 'speed fix':
* html, * html body{
    background: #fff url(image.jpg) fixed;
  }
offsetting the “fixed” element:
* html #content {
position: relative;
}
relevant HTML:
<div id="content">
<div id="fixme"><div> some fixed stuff here </div></div>

</div>

Yes, there may be the need for some extra elements in the source-code in some cases, but their presence won't disturb any browser. I can reuse them for the good browsers.

foreground as background – the art of stacking…

Take a look at this demo: fixing large element. The center-column has a quite large, fixed, background to illude transparency. That background will also stay fixed during scrolling in IE6. Only thing is: it's one of those “fixed” foreground-elements with background attached, and a reordered stacking, that creates the illusion in IE6.

Take the “large element” solution above, and add the following:

* html #content * {
position: relative;
z-index: 1;
}

Now all paragraphs, and whatever else inside #content, are layered on top of the “fixed” element with a background-image, and the illusion is almost perfect – even in IE6.

conclusion…

So, now I have most of the building-blocks needed to simulate 'position: fixed' relative to top of viewport in IE6. Combining the blocks in the right order and adding in the right values for each layout, is all that is left.

I've just started exploring the use of IE-expressions as workarounds for IE's lack of support for ordinary CSS, so I will probably be able to fine-tune my solutions and add some more in the near future.

sincerely  georg; sign

Hageland 10.jun.2006
last rev: 17.sep.2006

additions...

about…
…2006


fix me #1
fix me #2
fix me #3