37

I'm relatively new to jQuery, but so far what I've seen I like. What I want is for a div (or any element) to be across the top of the page as if "position: fixed" worked in every browser.

I do not want something complicated. I do not want giant CSS hacks. I would prefer if just using jQuery (version 1.2.6) is good enough, but if I need jQuery-UI-core, then that's fine too.

I've tried $("#topBar").scrollFollow(); <-- but that goes slow... I want something to appear really fixed.

Timothy Khouri
  • 31,315
  • 21
  • 88
  • 128
  • I just tried out the scrollFollow and it seems to work brilliantly. Not instantly like Timothy says, but if you're happy for it to glide up and down the page, it's perfect! – Paul Jan 13 '10 at 13:04

6 Answers6

61

Using this HTML:

<div id="myElement" style="position: absolute">This stays at the top</div>

This is the javascript you want to use. It attaches an event to the window's scroll and moves the element down as far as you've scrolled.

$(window).scroll(function() {
    $('#myElement').css('top', $(this).scrollTop() + "px");
});

As pointed out in the comments below, it's not recommended to attach events to the scroll event - as the user scrolls, it fires A LOT, and can cause performance issues. Consider using it with Ben Alman's debounce/throttle plugin to reduce overhead.

nickf
  • 537,072
  • 198
  • 649
  • 721
  • 3
    It isn't good idea to attach an event directly to the scroll event. See jQuery author on it: http://stackoverflow.com/questions/257250/what-is-the-simplest-jquery-way-to-have-a-positionfixed-always-at-top-div – neves Jan 21 '11 at 04:16
  • @Mathias, yes, and caching `$('#myElement')` would be even faster still. – nickf Mar 04 '11 at 12:35
  • 3
    Might be worth caching `$(window)` and `$('#myElement')` because you re-use these every time the scroll event fires. `var $window = $(window), $elem = $('#myElement'); $window.scroll(function() { $elem.css('top', $window.scrollTop() + 'px'); });` – Mathias Bynens Mar 07 '11 at 12:24
  • @nickf *facepalm* I missed that one for some reason. It’s more important than the `$(window)` caching, even! Thanks, comment edited. – Mathias Bynens Mar 07 '11 at 12:26
  • How would you add some value to the pixel? Currently #myElement is a half hidden to the top of viewport. Thanks. Edited: Never mind. Its CSS issue at original CSS. Reset the CSS, and fine: $window.scroll(function() { $elem.css({'top': $window.scrollTop() + 'px', 'margin': 0}); }); – swan Jul 31 '11 at 07:12
7

For those browsers that do support "position: fixed" you can simply use javascript (jQuery) to change the position to "fixed" when scrolling. This eliminates the jumpiness when scrolling with the $(window).scroll(function()) solutions listed here.

Ben Nadel demonstrates this in his tutorial: Creating A Sometimes-Fixed-Position Element With jQuery

Schmoove
  • 116
  • 1
  • 4
7

Beautiful! Your solution was 99%... instead of "this.scrollY", I used "$(window).scrollTop()". What's even better is that this solution only requires the jQuery1.2.6 library (no additional libraries needed).

The reason I wanted that version in particular is because that's what ships with MVC currently.

Here's the code:

$(document).ready(function() {
    $("#topBar").css("position", "absolute");
});

$(window).scroll(function() {
    $("#topBar").css("top", $(window).scrollTop() + "px");
});
Daniel
  • 10,864
  • 22
  • 84
  • 115
Timothy Khouri
  • 31,315
  • 21
  • 88
  • 128
2

HTML/CSS Approach

If you are looking for an option that does not require much JavaScript (and and all the problems that come with it, such as rapid scroll event calls), it is possible to gain the same behavior by adding a wrapper <div> and a couple of styles. I noticed much smoother scrolling (no elements lagging behind) when I used the following approach:

JS Fiddle

HTML

<div id="wrapper">
  <div id="fixed">
    [Fixed Content]
  </div><!-- /fixed -->
  <div id="scroller">
    [Scrolling Content]
  </div><!-- /scroller -->
</div><!-- /wrapper -->

CSS

#wrapper { position: relative; }
#fixed { position: fixed; top: 0; right: 0; }
#scroller { height: 100px; overflow: auto; }

JS

//Compensate for the scrollbar (otherwise #fixed will be positioned over it).
$(function() {
  //Determine the difference in widths between
  //the wrapper and the scroller. This value is
  //the width of the scroll bar (if any).
  var offset = $('#wrapper').width() - $('#scroller').get(0).clientWidth;

  //Set the right offset
  $('#fixed').css('right', offset + 'px');​
});

Of course, this approach could be modified for scrolling regions that gain/lose content during runtime (which would result in addition/removal of scrollbars).

Mac Attack
  • 952
  • 10
  • 21
1

For anyone still looking for an easy solution in IE 6. I created a plugin that handles the IE 6 position: fixed problem and is very easy to use: http://www.fixedie.com/

I wrote it in an attempt to mimic the simplicity of belatedpng, where the only changes necessary are adding the script and invoking it.

tbranyen
  • 8,507
  • 1
  • 21
  • 18
  • Doesn't work correctly with an item whose "top" is not 0: if I set the left to have a "top" of 50px, this script puts it at 0. – avdd Oct 15 '10 at 00:51
  • @avdd as you can see at the http://fixedie.com/demo/demo.html page, it supports a variety of CSS properties, and top:0 is not required at all. If you're having trouble feel free to contact me, and if you find bugs please report at: http://github.com/lark/FixedIE/issues – tbranyen Oct 15 '10 at 12:44
  • 1
    Would it be still possible to get the plugin? Now it's a 403 forbidden. – Paolo Feb 06 '12 at 15:29
  • 2
    Nah I phased it out. Two years is a long time and IE 6 isn't on my radar anymore. – tbranyen Feb 09 '12 at 06:50
0

In a project, my client would like a floating box in another div, so I use margin-top CSS property rather than top in order to my floating box stay in its parent.