How do I get an element to scroll into view, using jQuery?

JavascriptJquery

Javascript Problem Overview


I have an HTML document with images in a grid format using <ul><li><img.... The browser window has both vertical & horizontal scrolling.

Question: When I click on an image <img>, how then do I get the whole document to scroll to a position where the image I just clicked on is top:20px; left:20px ?

I've had a browse on here for similar posts...although I'm quite new to JavaScript, and want to understand how this is achieved for myself.

Javascript Solutions


Solution 1 - Javascript

There's a DOM method called scrollIntoView, which is supported by all major browsers, that will align an element with the top/left of the viewport (or as close as possible).

$("#myImage")[0].scrollIntoView();

On supported browsers, you can provide options:

$("#myImage")[0].scrollIntoView({
    behavior: "smooth", // or "auto" or "instant"
    block: "start" // or "end"
});

Alternatively, if all the elements have unique IDs, you can just change the hash property of the location object for back/forward button support:

$(document).delegate("img", function (e) {
    if (e.target.id)
        window.location.hash = e.target.id;
});

After that, just adjust the scrollTop/scrollLeft properties by -20:

document.body.scrollLeft -= 20;
document.body.scrollTop -= 20;

Solution 2 - Javascript

Since you want to know how it works, I'll explain it step-by-step.

First you want to bind a function as the image's click handler:

$('#someImage').click(function () {
    // Code to do scrolling happens here
});

That will apply the click handler to an image with id="someImage". If you want to do this to all images, replace '#someImage' with 'img'.

Now for the actual scrolling code:

  1. Get the image offsets (relative to the document):

     var offset = $(this).offset(); // Contains .top and .left
    
  2. Subtract 20 from top and left:

     offset.left -= 20;
     offset.top -= 20;
    
  3. Now animate the scroll-top and scroll-left CSS properties of <body> and <html>:

     $('html, body').animate({
         scrollTop: offset.top,
         scrollLeft: offset.left
     });
    

Solution 3 - Javascript

Simplest solution I have seen

var offset = $("#target-element").offset();
$('html, body').animate({
    scrollTop: offset.top,
    scrollLeft: offset.left
}, 1000);

[Tutorial Here][1] [1]: https://www.abeautifulsite.net/smoothly-scroll-to-an-element-without-a-jquery-plugin-2

Solution 4 - Javascript

There are methods to scroll element directly into the view, but if you want to scroll to a point relative from an element, you have to do it manually:

Inside the click handler, get the position of the element relative to the document, subtract 20 and use window.scrollTo:

var pos = $(this).offset();
var top = pos.top - 20;
var left = pos.left - 20;
window.scrollTo((left < 0 ? 0 : left), (top < 0 ? 0 : top));

Solution 5 - Javascript

Have a look at the jQuery.scrollTo plugin. Here's a demo.

This plugin has a lot of options that go beyond what native scrollIntoView offers you. For instance, you can set the scrolling to be smooth, and then set a callback for when the scrolling finishes.

You can also have a look at all the JQuery plugins tagged with "scroll".

Solution 6 - Javascript

Here's a quick jQuery plugin to map the built in browser functionality nicely:

$.fn.ensureVisible = function () { $(this).each(function () { $(this)[0].scrollIntoView(); }); };

...

$('.my-elements').ensureVisible();

Solution 7 - Javascript

After trial and error I came up with this function, works with iframe too.

function bringElIntoView(el) {    
    var elOffset = el.offset();
    var $window = $(window);
    var windowScrollBottom = $window.scrollTop() + $window.height();
    var scrollToPos = -1;
    if (elOffset.top < $window.scrollTop()) // element is hidden in the top
        scrollToPos = elOffset.top;
    else if (elOffset.top + el.height() > windowScrollBottom) // element is hidden in the bottom
        scrollToPos = $window.scrollTop() + (elOffset.top + el.height() - windowScrollBottom);
    if (scrollToPos !== -1)
        $('html, body').animate({ scrollTop: scrollToPos });
}

Solution 8 - Javascript

My UI has a vertical scrolling list of thumbs within a thumbbar The goal was to make the current thumb right in the center of the thumbbar. I started from the approved answer, but found that there were a few tweaks to truly center the current thumb. hope this helps someone else.

markup:

<ul id='thumbbar'>
    <li id='thumbbar-123'></li>
    <li id='thumbbar-124'></li>
    <li id='thumbbar-125'></li>
</ul>

jquery:

// scroll the current thumb bar thumb into view
heightbar 	= $('#thumbbar').height();
heightthumb	= $('#thumbbar-' + pageid).height();
offsetbar 	= $('#thumbbar').scrollTop();


$('#thumbbar').animate({
    scrollTop: offsetthumb.top - heightbar / 2 - offsetbar - 20
});

Solution 9 - Javascript

Just a tip. Works on firefox only

Element.scrollIntoView();

Solution 10 - Javascript

Simple 2 steps for scrolling down to end or bottom.

Step1: get the full height of scrollable(conversation) div.

Step2: apply scrollTop on that scrollable(conversation) div using the value obtained in step1.

var fullHeight = $('#conversation')[0].scrollHeight;

$('#conversation').scrollTop(fullHeight);

Above steps must be applied for every append on the conversation div.

Solution 11 - Javascript

After trying to find a solution that handled every circumstance (options for animating the scroll, padding around the object once it scrolls into view, works even in obscure circumstances such as in an iframe), I finally ended up writing my own solution to this. Since it seems to work when many other solutions failed, I thought I'd share it:

function scrollIntoViewIfNeeded($target, options) {

	var options = options ? options : {},
    $win = $($target[0].ownerDocument.defaultView), //get the window object of the $target, don't use "window" because the element could possibly be in a different iframe than the one calling the function
	$container = options.$container ? options.$container : $win,		
	padding = options.padding ? options.padding : 20,
	elemTop = $target.offset().top,
	elemHeight = $target.outerHeight(),
	containerTop = $container.scrollTop(),
	//Everything past this point is used only to get the container's visible height, which is needed to do this accurately
	containerHeight = $container.outerHeight(),
	winTop = $win.scrollTop(),
	winBot = winTop + $win.height(),
	containerVisibleTop = containerTop < winTop ? winTop : containerTop,
	containerVisibleBottom = containerTop + containerHeight > winBot ? winBot : containerTop + containerHeight,
	containerVisibleHeight = containerVisibleBottom - containerVisibleTop;

	if (elemTop < containerTop) {
		//scroll up
		if (options.instant) {
			$container.scrollTop(elemTop - padding);
		} else {
			$container.animate({scrollTop: elemTop - padding}, options.animationOptions);
		}
	} else if (elemTop + elemHeight > containerTop + containerVisibleHeight) {
		//scroll down
		if (options.instant) {
			$container.scrollTop(elemTop + elemHeight - containerVisibleHeight + padding);
		} else {
			$container.animate({scrollTop: elemTop + elemHeight - containerVisibleHeight + padding}, options.animationOptions);
		}
	}
}

$target is a jQuery object containing the object you wish to scroll into view if needed.

options (optional) can contain the following options passed in an object:

options.$container - a jQuery object pointing to the containing element of $target (in other words, the element in the dom with the scrollbars). Defaults to the window that contains the $target element and is smart enough to select an iframe window. Remember to include the $ in the property name.

options.padding - the padding in pixels to add above or below the object when it is scrolled into view. This way it is not right against the edge of the window. Defaults to 20.

options.instant - if set to true, jQuery animate will not be used and the scroll will instantly pop to the correct location. Defaults to false.

options.animationOptions - any jQuery options you wish to pass to the jQuery animate function (see http://api.jquery.com/animate/). With this, you can change the duration of the animation or have a callback function executed when the scrolling is complete. This only works if options.instant is set to false. If you need to have an instant animation but with a callback, set options.animationOptions.duration = 0 instead of using options.instant = true.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionNasirView Question on Stackoverflow
Solution 1 - JavascriptAndy EView Answer on Stackoverflow
Solution 2 - JavascriptDavid TangView Answer on Stackoverflow
Solution 3 - JavascriptMatt WatsonView Answer on Stackoverflow
Solution 4 - JavascriptFelix KlingView Answer on Stackoverflow
Solution 5 - JavascriptRob Stevenson-LeggettView Answer on Stackoverflow
Solution 6 - JavascriptRobView Answer on Stackoverflow
Solution 7 - JavascriptTone ŠkodaView Answer on Stackoverflow
Solution 8 - JavascriptxeoView Answer on Stackoverflow
Solution 9 - Javascriptwp studentView Answer on Stackoverflow
Solution 10 - JavascriptShiva Kumar PView Answer on Stackoverflow
Solution 11 - JavascriptdallinView Answer on Stackoverflow