17

I would like to center a div by clicking it. So if I'm clicking a div I want it to scroll to the center of the browser viewport. I don't want to use anchor points like the guides and examples I've seen. How can I achieve this?

Rudu
  • 15,682
  • 4
  • 47
  • 63
Designon
  • 183
  • 1
  • 1
  • 8
  • $('html,body').animate({ scrollTop: $("#divToBeScrolledTo").offset().top; }); I don't want to have to specify what div it is. I would like to center the div im clicking. So if im browsing pictures i want to center the picture in the browser viewport. And because people can add their own pictures its not convenient to manually add anchor points :) – Designon Jul 17 '12 at 19:14
  • 1
    Of course you need to specify which div you want to scroll to. Don't you know what you want to center? – Bergi Jul 17 '12 at 19:20
  • Haha yes of course! but cant i do like ScrollTo('this') or something? – Designon Jul 17 '12 at 19:27
  • No, because the string "this" is no valid selector. Read [the docs](http://api.jquery.com/jQuery/) on what the jQuery constructor is able to handle. – Bergi Jul 17 '12 at 19:34
  • So if i got "random" ids how to i pare selector and object ? :) – Designon Jul 17 '12 at 19:48
  • Why random ids? Do you know that div (e.g. having a variable pointing to the node) or don't you? – Bergi Jul 17 '12 at 20:21

4 Answers4

27

In some way you have to identify the clickable elements. I build an example, that uses the class-attribute for that.

Step 1

This is the script, that does the work:

$('html,body').animate({
    scrollTop: $(this).offset().top - ( $(window).height() - $(this).outerHeight(true) ) / 2
}, 200);

What you tried is to scroll the container to the top of the page. You also have to calculate and subtract the difference between the container height and the viewport height. Divide this by two (as you want to have the same space on top and bottom and you are ready to go.

Step 2

Then you add the click handler to all the elements:

$(document).ready(function () {
    $('.image').click( function() {
        $('html,body').animate({ scrollTop: $(this).offset().top - ( $(window).height() - $(this).outerHeight(true) ) / 2  }, 200);
    });
});

Step 3

Set up some HTML/CSS:

<style>

    div.image {

        border:     1px solid red;
        height:     500px;
        width:      500px;
    }

</style>

<div class="image">1</div>
<div class="image">2</div>
<div class="image">3</div>
<div class="image">4</div>
<div class="image">5</div>

And you're done.

Check out the demo

Try it yourself http://jsfiddle.net/insertusernamehere/3T9Py/

insertusernamehere
  • 23,204
  • 9
  • 87
  • 126
6

I know this question is old, but right now, you can use scrollIntoView:

For example:

document.body.scrollIntoView({
  behavior: 'smooth',
  inline: 'center',
  block: 'center'
});
KBeDev
  • 387
  • 5
  • 9
  • Unfortunately, it doesn't work in older browsers. – AEB May 11 '21 at 10:56
  • ... and Safari https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView#browser_compatibility – Jan Molnár Jan 30 '23 at 23:07
  • Yes, Safari does not support options object parameter. To get this, you will need to use the page client height to calculate the center value. You can use the [scroll()](https://developer.mozilla.org/en-US/docs/Web/API/Element/scroll) or [scrollBy()](https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollBy) methods. These are fully supported by modern versions of Safari (14+). – KBeDev Jan 31 '23 at 19:59
5
HTMLElement.prototype.scrollToCenter = function(){
    window.scrollBy(0, this.getBoundingClientRect().top - (window.innerHeight>>1));
}

Achieved with pure JavaScript for Scrolling to Center in the vertical direction. And it's similar in the horizontal direction. I don't take elements' height into consideration, because they maybe larger than the height of screen.

Ciar
  • 51
  • 1
  • 2
4

I've got one slight modification to offer.
If the "adjustment factor" i.e. ( $(window).height() - $(this).outerHeight(true) ) / 2 is < 0 you can get undesirable results whereby you overshoot that element in the viewport with your scroll.

I added a max(0,adjustment factor) to correct :

    function scrollIntoView(el) {
    
        var offsetTop = $j(el).offset().top;
        var adjustment = Math.max(0,( $j(window).height() - $j(el).outerHeight(true) ) / 2);
        var scrollTop = offsetTop - adjustment;
    
        $j('html,body').animate({
            scrollTop: scrollTop
        }, 200);
    }
herringtown
  • 608
  • 5
  • 11
  • 1
    @insertusernamehere But this way if the element is bigger than window height it will be fully visible, not centered, but visible from start, this is working like "center this until it won't fit, then just scroll the view to element start" – Programista Aug 04 '13 at 22:37
  • 1
    @Programista Ah, thanks for making that clear. Now I get what was meant by "*overshoot*". Depending on the use case (really center everything or center if applicable), this is another solution and here's a [fiddle to demonstrate it](http://jsfiddle.net/vZGzR/). – insertusernamehere Aug 05 '13 at 22:39
  • great thanks..vanillarized it for my needs..workin like a charm =) – Can Rau Jun 11 '16 at 07:59
  • What would this be in Vanilla JavaScript? – LStarky Mar 03 '17 at 17:45