One of the major positioning schemes of CSS-2 is fixed positioning. It theoretically allows the positioning of block-level elements with respect to the user agent veiwport rather than the scrollable browser window. Because fixed blocks don't scroll with the window, a single page can emulate the look of a frame-based layout without all the nasty complications. Great, a couple of lines of CSS and we can trash the whole frameset -- you're going to need more than scroll-bars to escape the clutches of my navigation. Now I know that many people find fixed positioning annoying but I love how it creates the illusion of 3-dimensionality through parallax and scrolling. If you think this is bad, wait until I figure out how to make elements scroll at variable rates. Here's a simple example: fixtest mark 1.
Unfortunately, in the world of CSS things are rarely so easy. As you might have noticed, the example doesn't work in the world's most popular browsers, Windows Internet Explorer. But all is not lost. Internet Explorer versions 5+ can handle CSS overflow properties that allow us to put scroll-bars on any block-level element. So, for Internet Explorer we can emulate fixed positioning by taking the scrolling behavior away from the root element, giving the scrolling behavior to a child of the root, and using absolute positioning to put the element we want to fix on top. The trick to making it 'seamless' is to give our scrolling child 100% of the height and width of the viewport.
The only problem is that all this trickery will drive any sane browser crazy.
So we've got to hide most of the changes from browsers other than Internet
Explorer and have them position the fixed element the old-fashioned way.
Though this can be accomplished through a number of different hacks, I chose
to use the *
html method because it targets ie5 and 6 very specifically, all other
browsers will ignore it, it validates, and the only possible future problem
is if the next Internet Explorer doesn't understand the selector (not likely)
or position fixed (I'm
pessimistic). For some reason I have real aesthetic difficulties with
voice-family:"\"{\"" and the like and don't like polluting
my html with conditional
comments. Here's an example that should work in most modern browsers:
fixtest mark 2.
The second example doesn't work when ie6 is in quirks (backwards compatibility) mode and doesn't work in ie5. While that didn't bother me too much at first because my pages are rendered in standards mode, my logs show a lot of people coming through with ie5 (mainly searching for "what does nature abhors a vacuum mean?"). So I experimented a little and found that removing the fixed elements from the scrolling element in the html source code could solve the problem. So here's fixtest mark 3 which should work in ie5+ and most other modern browsers (still kind of wonky on ie mac).
The final test page was made to show that the method can be combined with other positioning schemes and doesn't have to look like a frame. With a little trial and error, this method is extensible though fragile. I've seen lots of bizarre behavior from Internet Explorer: collapsing pages (avoid hover background-color changes in the scrolling element), elements overlapping the scroll-bars (give ie 16px on the right), and positioning numbers that just don't add up (sometimes it's necessary to send ie different numbers from the other browsers). So, while I can't say that this technique is 'prime time' and I doubt we'll see it on aol's new CSS front-page anytime soon, it's stable enough for me. If anyone does decide to try it out, let me know and I'll do what I can to help out.
Thanks to Position is Everything and Tagsoup for the prior art.