14

I need the page to scroll just so that an element is visible.

Options I've tried:

  • jQuery's scrollTo: the problem is that the page scrolls so that the element is on top (or at least it tries to do that, much like how this works: <a name="xyz"> / <a href="#xyz">). I want the minimum amount of scrolling, so that the entire element is visible (and, if the element is too tall, work like the anchor there).

  • scrollIntoView: awful. I want it to scroll smoothly (like $.scrollTo($('#id1'), 'fast');). Also, it doesn't seem to do what I want either.

1

3 Answers 3

19

What you need to do is identify the position within the page of the element, top and bottom (and left/right if you are considering horizontal scrolling). Then identify the current position of the viewport on the window, the scrollTop of the window should then be animated to whatever value will bring the other just in to view.

I just knocked up the following in this editor, so it's untested, but will give you the general idea for a plugin.

Updated - to show version that worked for the OP, as well as a smoother version

jQuery.fn.scrollMinimal = function(smooth) {
  var cTop = this.offset().top;
  var cHeight = this.outerHeight(true);
  var windowTop = $(window).scrollTop();
  var visibleHeight = $(window).height();

  if (cTop < windowTop) {
    if (smooth) {
      $('body').animate({'scrollTop': cTop}, 'slow', 'swing');
    } else {
      $(window).scrollTop(cTop);
    }
  } else if (cTop + cHeight > windowTop + visibleHeight) {
    if (smooth) {
      $('body').animate({'scrollTop': cTop - visibleHeight + cHeight}, 'slow', 'swing');
    } else {
      $(window).scrollTop(cTop - visibleHeight + cHeight);
    }
  }
};

$('#item').scrollMinimal();
6
  • This looks great. Doesn't work as-is, but I'm testing to see if I can make it work...
    – cambraca
    Commented Nov 18, 2010 at 18:15
  • I replaced $(window).animate({'scrollTop': the_number}, etc) for $.scrollTo(the_number, etc) and it worked! Thanks a bunch!!
    – cambraca
    Commented Nov 18, 2010 at 18:21
  • The $(window).animate() call should have been $('body').animate() - your version using the scrollTop() is direct enough but not as smooth. If you are actually using .scrollTo() then great, though that is a plugin now I believe.
    – Orbling
    Commented Nov 18, 2010 at 18:35
  • Yeah, that's a plugin. I was just concerned about $('body').animate not working in some bizarre browser version, so I feel better leaving the scrolling to the plugin (which I'm sure is 105% tested in all browsers past, present, and future)
    – cambraca
    Commented Nov 18, 2010 at 19:23
  • 1
    Just thought I would let you know this still works many years later, and it's really useful as there still isn't many other ways to do this. Commented Mar 12, 2016 at 13:25
15

There's a plugin for just what you need

I don't want to copy the code from blog post, because it can get outdated (due to upgrades). But anyway. You can find all details and code about the .scrollintoview() jQuery plugin on blog post.

Usage

Contrary to scrollTo() plugin where you have to provide scrollable element this plugin only requires you to provide the element you'd like to scroll into view. Plugin finds nearest scrollable ancestor (with scrollbars) and scrolls to the element with animation, so user doesn't loose track of their position in the page.

The good thing is also that it won't scroll anything if element is already within visible boundaries of scrollable ancestor.

 $("ElementSelector").scrollintoview();

That's it most of the time. But if you need to set some additional settings, there are some you can change and provide custom behaviour:

scrollintoview: function (options) {
    /// <summary>Scrolls the first element in the set into view by scrolling its closest scrollable parent.</summary>
    /// <param name="options" type="Object">Additional options that can configure scrolling:
    ///        duration (default: "fast") - jQuery animation speed (can be a duration string or number of milliseconds)
    ///        direction (default: "both") - select possible scrollings ("vertical" or "y", "horizontal" or "x", "both")
    ///        complete (default: none) - a function to call when scrolling completes (called in context of the DOM element being scrolled)
    /// </param>
    /// <return type="jQuery">Returns the same jQuery set that this function was run  on.</return>
4
  • 1
    @AaronDigulla: It is better than my answer yes, and about five times the size, a proper plugin - rather than something just knocked up to provide a quick solution, as it states in the answer. Sometimes a chunky plugin is less desirable than a small solution. (Apologies for reviving a long dead post, just noticed this answer)
    – Orbling
    Commented Jun 19, 2012 at 14:06
  • @Orbling: but doesn't your solution also use an existing plugin scrollTo() which is even larger than mine? It is likely more flexible but serves a bit different purpose as well... Commented Jun 19, 2012 at 14:56
  • @RobertKoritnik: Not knocking your solution at all Robert, I gave it +1, just noting the differences, which is mainly a code size thing. Mine only uses .scrollTop() which is a built-in method, no other plugins, AFAIK. It was a long time ago, I only revived it due to getting a badge, which made me look, lol. ;-)
    – Orbling
    Commented Jun 19, 2012 at 15:08
  • 2
    @Orbling: Oh sorry. My bay. By glancing at your code I though you were using scrollTo plugin and not build in jQuery scrollTop function. Sorry about that. And I didn't feel like being knocked down. No. Just got me checking since I've seen a new comment. :) Great code anyway. Commented Jun 19, 2012 at 15:23
1

FYI, jQuery scrolling element into viewport plugins alternative:

Not the answer you're looking for? Browse other questions tagged or ask your own question.