Handling Onscroll

Way back when I first implemented the fixed comments, I used JavaScript to duplicate the effect in Internet Explorer 6. It was really choppy but it worked. This type of script has been around since the Age of DHTML but I still get the occasional person asking how this was done. So here's the original code I had:

function window_onscroll()
{

  var el = document.getElementById('postcomment');
  if(el!=null)
  {
    if(typeof(document.media)=='string')
    {// only do this for ie
      var s;
      // scrolling offset calculation via www.quirksmode.org
      if (self.pageYOffset){
        s = self.pageYOffset;
      }else if (document.documentElement && document.documentElement.scrollTop) { 
        s = document.documentElement.scrollTop; 
      }else if (document.body) { 
        s = document.body.scrollTop; 
      }
      el.style.top= s + 30;
    }

    if(typeof(window.print)=='function')
    {// only do if not ie
      var x;
      // scrolling offset calculation via www.quirksmode.org
      if (self.pageXOffset){ 
        x = self.pageXOffset;
      }else if (document.documentElement && document.documentElement.scrollTop){ 
        x = document.documentElement.scrollLeft; 
      }else if (document.body) { 
        x = document.body.scrollLeft;
      }
      el.style.left = (548 - x) + "px";
    }
  }
}

The first block was the IE-only code that checked the vertical scrolling offset and positioned the box accordingly. This actually has an interesting effect in browsers that support position:fixed. As the page slides up, the element slides down.

Looking back on this code, checking for pageYOffset was completely unnecessary since this was for Internet Explorer only and it doesn't support that. Likewise, this code hasn't been tested in IE7 so it's quite likely that this code would still execute despite support for fixed positioning.

The second block of code was for browsers that supported position:fixed. When using fixed positioning, the element is fixed to the viewport. If there's a horizontal scrollbar and the page slides to the left, you need the fixed element to slide with it. Again, looking back at the code, I didn't need the superfluous else/if statements but there you have it.

Published February 23, 2007
Categorized as JavaScript
Short URL: http://snook.ca/s/770

Conversation

11 Comments · RSS feed
Jesper Bram said on February 23, 2007

Smart trick, not sure if I think it's a bit much or visually confusing, but it made me comment, so something must be working.

Thanks for sharing the code.

Brett Mitchell said on February 23, 2007

Hey Jonathan,

Just thought I'd mention that position:fixed; CAN be implemented in IE without javascript.

Stu Nichols' emulating position fixed for Internet Explorer' works for IE6.

Just take a peek at the source code to see that all it takes is a setting of height:100% for the body (with overflow-y:auto) and it works.

Anything that is position:absolute; or position:relative; will now be FIXED in IE6.

Might not be applicable in your case, seeing that you want to provide the effect for IE5.5 too presumably, but for others, it may be an option.

Riddle said on February 23, 2007

Have you tried expressions?

Jonathan Snook said on February 23, 2007

@Brett: yeah, I'm familiar with that technique. I haven't played with it and I'd be concerned about the side effects of relying on overflow.

@Riddle: I'd have assumed that expressions would result in the same performance as an onscroll event but I'm not noticing any flickr. Is the fixed background on the body required to eliminate the flicker? Otherwise, it might be worth it for me to add back in for IE6 users.

Derek Allard said on February 23, 2007

Fixed comments and sidebar? What kind of loser would ever do that? Oh wait…

(well done! ;) )

Riddle said on February 23, 2007

Yep, that's the hidden magic of background-attachment: fixed on any image (or url() reference to fake file)

I also prefer expressions, because I always include additional stylesheets for IE in conditional comments. I don't want to do the same with JS. :-)

Moreover, expressions are designed to respond to any changes in DOM / CSS / events.

Karinne said on February 26, 2007

I'm a tad confused here. The comment box doesn't act at all in IE6 like it does in Firefox?! I mean ... it doesn't stay there on the screen while I scroll. So ... what's the use of the JS then?

It is Monday morning, so ... it is possible that my brain hasn't awakened yet! :p

Jonathan Snook said on February 26, 2007

@Karinne: yeah, I guess I wasn't entirely clear. When I redesigned, I decided to drop support for IE6 and stopped using this particular piece of code (hence, it doesn't move in IE6). But since people asked for the code, I thought I'd share.

jason said on March 04, 2007

this is a cool!

tom said on June 15, 2007

How's about a new version or perhaps some simple examples of what the best method to achieve this is now? (with IE5.5 to IE7 catered for) Pleeeeeeeeeeeese!

I found your site mentioned in Budd, Moll and Collison's "CSS Mastery" (Friends Of Ed publishing) and I'm trying to get it to work here...
http://www.runninghead.com/links.html
If I succeed I'll post a slim and modern version here but I'm no guru.

Expressions sound elegant (for an IE proprietary hack) and Conditional Comments also appeal as we use them anyway.
How few lines might one really need to get IE (v5 to v7 inclusive) to behave like a compliant browser?

Ps- gorgeous site you've got here- beautiful fresh design!

tom said on June 16, 2007

Found this in an excellent article on Mark "Tarquin" Wilton-Jones' http://www.howtocreate.co.uk/fixedPosition.html site.


<style type="text/css">
#fixme {
  /* Netscape 4, IE 4.x-5.0/Win and other lesser browsers will use this */
  position: absolute; right: 20px; bottom: 10px;
}
body > div#fixme {
  /* used by Opera 5+, Netscape6+/Mozilla, Konqueror, Safari, OmniWeb 4.5+, iCab, ICEbrowser */
  position: fixed;
}
</style>
<!--[if gte IE 5.5]>
<![if lt IE 7]>
<style type="text/css">
div#fixme {
  /* IE5.5+/Win - this is more specific than the IE 5.0 version */
  right: auto; bottom: auto;
  left: expression( ( -20 - fixme.offsetWidth + ( document.documentElement.clientWidth ? document.documentElement.clientWidth : document.body.clientWidth ) + ( ignoreMe2 = document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft ) ) + 'px' );
  top: expression( ( -10 - fixme.offsetHeight + ( document.documentElement.clientHeight ? document.documentElement.clientHeight : document.body.clientHeight ) + ( ignoreMe = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop ) ) + 'px' );
}
</style>
<![endif]>
<![endif]-->

Not bad, though tricky to follow at first.
Share and enjoy.

Sorry, comments are closed for this post. If you have any further questions or comments, feel free to send them to me directly.