343

I am trying to move the page to a <div> element.

I have tried the next code to no avail:

document.getElementById("divFirst").style.visibility = 'visible';
document.getElementById("divFirst").style.display = 'block';
Lekensteyn
  • 64,486
  • 22
  • 159
  • 192
C..
  • 6,897
  • 10
  • 30
  • 37
  • 2
    `visibility` and `display` are used for making elements (in)visible. Do you want to scroll the div in the screen? – Lekensteyn Feb 15 '11 at 18:05
  • 2
    What kind of focus? The same focus as you have when tabbing through form elements or focus in the sense of highlighting the element somehow? The only thing you do is to do display the element, which has not effect if it is already displayed. – Felix Kling Feb 15 '11 at 18:07
  • 1
    Focus as scrolling into view? – epascarello Feb 15 '11 at 18:07
  • 17
    [`el.scrollIntoView(true)`](https://developer.mozilla.org/en-US/docs/Web/API/Element.scrollIntoView) – Blazemonger Jun 09 '14 at 18:12
  • 1
    Does this answer your question? [JavaScript to scroll long page to DIV](https://stackoverflow.com/questions/68165/javascript-to-scroll-long-page-to-div) – Jishnu V S Aug 11 '22 at 06:24

20 Answers20

552

scrollIntoView works well:

document.getElementById("divFirst").scrollIntoView();

full reference in the MDN docs:
https://developer.mozilla.org/en-US/docs/Web/API/Element.scrollIntoView

schpet
  • 9,664
  • 6
  • 32
  • 35
  • 12
    @CameronMcCluskie it's only the weird "scrollIntoViewOptions" (smooth scrolling, etc) that has exclusive firefox support. the basic use i have in my answer should work on almost anything. – schpet Jul 17 '15 at 02:41
  • 8
    I confirm, as of Apr-16, it works under Opera and Chrome too. – lvr123 Apr 18 '16 at 09:05
  • 7
    When using this solution and you have a fixed navbar at the top, you need to consider that as well. A different solution might be more suitable such as windows.scrollTo(posX, posY) with properly calculated posY. – Manfred Jun 21 '16 at 04:46
  • 2
    Worked in Firefox, Opera, and Safari. – Jagdeep Singh Sep 07 '16 at 06:40
  • Don't see much of a difference in AnhSirk Dasarp's answer above and this one. They seem to behave exactly same to me. – Jagdeep Singh Sep 07 '16 at 06:43
  • I works in Edge too. I need only figure out if the element is already visible to avoid exceeding scrolls – Singagirl Oct 31 '16 at 18:36
  • 4
    [Here's another source (caniuse)](http://caniuse.com/#search=scrollIntoView) for browser compatibility of `scrollIntoView` – Nate Anderson Feb 28 '17 at 18:32
  • For some reason in my page this doesn't work. Only the solution of schpet (selected answer) works for me. – Gustavo Rodríguez Aug 02 '19 at 14:16
189

You can use an anchor to "focus" the div. I.e:

<div id="myDiv"></div>

and then use the following javascript:

// the next line is required to work around a bug in WebKit (Chrome / Safari)
location.href = "#";
location.href = "#myDiv";
Michael T
  • 370
  • 4
  • 16
Nikoloff
  • 4,050
  • 1
  • 17
  • 19
  • 17
    Chrome (WebKit) has a bug which causes the page not to scroll once the anchor is set. Use: `location.href="#";location.href="#myDiv"`. Using `id="myDiv"` is preferred over `name="myDiv"` and works too. – Lekensteyn Feb 15 '11 at 18:14
  • 8
    I had this exact problem, but the WebKit "fix" causes a problem for me in FF 3.6.13. It works without the "#" line, but if you add it, it goes to "#" and never attempts going to "#myDiv". I'll stick with the solution without the "#", which is working for me... woohoo! – TimFoolery Feb 21 '11 at 05:52
  • 2
    This doesn't work well for me because it adds all of these navigation events to the browser history and I can't easily go back to the previous page – bikeman868 Aug 17 '18 at 00:03
  • I think 'AnhSirk Dasarp' below is a better method to scroll desired element to the top of the visible screen. – Curious101 Sep 20 '19 at 14:56
  • What if the scroller is in a inner div? –  May 07 '20 at 19:50
  • 1
    var elmnt = document.getElementById("content");elmnt.scrollIntoView(); – Abhi May 14 '20 at 13:26
  • schpet's answer below should be the accepted answer. – Cagy79 Dec 01 '20 at 13:54
  • @Cagy79 probably both should be used. In Chrome 97 for Windows 10 pc, `scrollIntoView();` wasn't enough to get the job done. It wouldn't scroll all the way into view. With this before the scroll into view it is better, still a bit jumpy... as I am typing this, I have the idea to use another `scrollIntoView();` to load the container, then scroll the subelement into view... Ima try it. Edit: Smoother than a baby's butt. – Shmack Feb 01 '22 at 19:35
  • You can use `location.hash` too. Here's [the reference](https://developer.mozilla.org/en-US/docs/Web/API/Location/hash) – Kunal Phaltankar Sep 13 '22 at 09:29
  • Hi from the future (now is 2023) .. :) does this thing work perfectly now, I am fed up with scrollTo, offsetTop and scrollIntoView bugs on Apple devices? – Vitaliy Terziev Jan 26 '23 at 19:31
  • This doesn't work if you are already on a site with a "#" in it. For example buildbot uses "#...." to activate different views with different dynamic content and replacing the href fails then. While simply scrolling into view works. – Johannes Schaub - litb Jun 16 '23 at 14:33
100

For Chrome and Firefox

I've been looking a bit into this and I figured this one out which somehow feels like the most natural way to do it. Of course, this is my personal favorite scroll now. :)

const y = element.getBoundingClientRect().top + window.scrollY;
window.scroll({
  top: y,
  behavior: 'smooth'
});

For IE, old Edge and old Safari supporters

Note that window.scroll({ ...options }) is not supported on IE, Edge and Safari. In that case it's most likely best to use element.scrollIntoView(). (Supported on IE 6). You can most likely (read: untested) pass in options without any side effects.

These can of course be wrapped in a function that behaves according to which browser is being used.

Caveman
  • 2,527
  • 1
  • 17
  • 18
  • 4
    Working like charm :) – midzer Aug 28 '18 at 01:01
  • 1
    This is the only solution which worked for me with Chrome. – wkille Feb 08 '19 at 15:37
  • 1
    I wanted to take your solution, as it is possible to fine tune the position (in my case y-80). It seems, as var element = document.getElementById("Div"); is missing in your example? Further it don't work with IE11. IE11 don't know window.scrollY - we have to use window.pageYOffset instead to receive a value. After I have changed that, I had various (not to comprehend) jquery errors (of course - as mostly - only in IE11. Therfore, I have implemented document.getElementById("divFirst").scrollIntoView(); and then $(window).scrollTop($(window).scrollTop() - 80); what works with all Browsers. – FredyWenger May 13 '19 at 14:15
  • Not supported on Safari (passing options to `window.scroll` – Shining Love Star Jul 21 '19 at 15:32
  • Thanks for the comments, I updates the answer to include browser compatability. – Caveman Nov 08 '19 at 22:18
  • Hey this code is to scroll up. What if we want to scroll down? I tried using 'bottom' property instead of 'top'. But that doesn't seem to be working... Any idea – Anant Shekhar Apr 27 '23 at 17:33
  • @AnantShekhar Sure. If you want to scroll past the element so that the bottom is just out of view from the top then use `window.scrollY + element.getBoundingClientRect().bottom` insteadof `top`. If you want the bottom to be at the bottom of the page then it's `window.scrollY + element.getBoundingClientRect().bottom - window.innerHeight`. Does that work for you? – Caveman May 02 '23 at 11:18
44

The best, shortest answer that what works even with animation effects:

var scrollDiv = document.getElementById("myDiv").offsetTop;
window.scrollTo({ top: scrollDiv, behavior: 'smooth'});

If you have a fixed nav bar, just subtract its height from top value, so if your fixed bar height is 70px, line 2 will look like:

window.scrollTo({ top: scrollDiv-70, behavior: 'smooth'});

Explanation: Line 1 gets the element position Line 2 scroll to element position; behavior property adds a smooth animated effect

DAVID AJAYI
  • 1,912
  • 20
  • 13
  • Really cool, but doesn't yet work on Safari and some other browsers. Does work with this polyfill https://github.com/iamdustan/smoothscroll though. ;) – Íhor Mé Nov 30 '19 at 18:53
  • 1
    I think `offsetTop` is wrong in general. I think you want `getBoundingClientRect(...).y` or `.top`. – Timmmm Apr 21 '23 at 08:55
32

We can implement by 3 Methods:

Note:

"automatic-scroll" => The particular element

"scrollable-div" => The scrollable area div

Method 1:

document.querySelector('.automatic-scroll').scrollIntoView({
     behavior: 'smooth'
});

Method 2:

location.href = "#automatic-scroll";

Method 3:

$('#scrollable-div').animate({
   scrollTop: $('#automatic-scroll').offset().top - $('#scrollable-div').offset().top + 
   $('#scrollable-div').scrollTop()
})

Important notice: method 1 & method 2 will be useful if the scrollable area height is "auto". Method 3 is useful if we using the scrollable area height like "calc(100vh - 200px)".

Muthulakshmi M
  • 651
  • 7
  • 8
18

You can set focus to element. It works better than scrollIntoView

node.setAttribute('tabindex', '-1')

node.focus()

node.removeAttribute('tabindex')

ZhenyaUsenko
  • 393
  • 4
  • 8
  • 1
    Oh man, you saved my day. Tested lots of stuff but this one was the only thing that worked for me and it's supported any all the browsers. Btw I created an input and gave 1px height and width and did focus on the input.it works great. Thanks – Martian.titan Mar 31 '20 at 03:27
  • actually it's a bad approaching for accessibility, and you cannot add smooth animation... i would try using window.scrollTo, but it might be error-prone on react apps since your component wont scroll due to its in another screen element, such as 'root', or whatever... the best here would be using scrollIntoView... although it doesn't work on iOS currently... – Code Drop Jan 17 '23 at 13:12
11

Try this:

var divFirst = document.getElementById("divFirst");
divFirst.style.visibility = 'visible'; 
divFirst.style.display = 'block';  
divFirst.tabIndex = "-1";  
divFirst.focus();

e.g @:

http://jsfiddle.net/Vgrey/

Chandu
  • 81,493
  • 19
  • 133
  • 134
  • I only want to emphasize that the DOM property is `element.tabIndex` but not `element.tabindex`; the second one works on Firefox but not on Chrome (at least when I tried it some time ago). Of course, used as an HTML attribute both `tabIndex` and `tabindex` work (and on XHTML, `tabindex` must be used) – Oriol Mar 23 '13 at 22:01
  • Doesn't work if the div is already focused. Need `div.blur()` first. – Polv May 03 '23 at 05:16
7

Here's a function that can include an optional offset for those fixed headers. No external libraries needed.

function scrollIntoView(selector, offset = 0) {
  window.scroll(0, document.querySelector(selector).offsetTop - offset);
}

You can grab the height of an element using JQuery and scroll to it.

var headerHeight = $('.navbar-fixed-top').height();
scrollIntoView('#some-element', headerHeight)

Update March 2018

Scroll to this answer without using JQuery

scrollIntoView('#answer-44786637', document.querySelector('.top-bar').offsetHeight)
HarlemSquirrel
  • 8,966
  • 5
  • 34
  • 34
6

To scroll to a given element, just made this javascript only solution below.

Simple usage:

EPPZScrollTo.scrollVerticalToElementById('signup_form', 20);

Engine object (you can fiddle with filter, fps values):

/**
 *
 * Created by Borbás Geri on 12/17/13
 * Copyright (c) 2013 eppz! development, LLC.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
 * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 */


var EPPZScrollTo =
{
    /**
     * Helpers.
     */
    documentVerticalScrollPosition: function()
    {
        if (self.pageYOffset) return self.pageYOffset; // Firefox, Chrome, Opera, Safari.
        if (document.documentElement && document.documentElement.scrollTop) return document.documentElement.scrollTop; // Internet Explorer 6 (standards mode).
        if (document.body.scrollTop) return document.body.scrollTop; // Internet Explorer 6, 7 and 8.
        return 0; // None of the above.
    },

    viewportHeight: function()
    { return (document.compatMode === "CSS1Compat") ? document.documentElement.clientHeight : document.body.clientHeight; },

    documentHeight: function()
    { return (document.height !== undefined) ? document.height : document.body.offsetHeight; },

    documentMaximumScrollPosition: function()
    { return this.documentHeight() - this.viewportHeight(); },

    elementVerticalClientPositionById: function(id)
    {
        var element = document.getElementById(id);
        var rectangle = element.getBoundingClientRect();
        return rectangle.top;
    },

    /**
     * Animation tick.
     */
    scrollVerticalTickToPosition: function(currentPosition, targetPosition)
    {
        var filter = 0.2;
        var fps = 60;
        var difference = parseFloat(targetPosition) - parseFloat(currentPosition);

        // Snap, then stop if arrived.
        var arrived = (Math.abs(difference) <= 0.5);
        if (arrived)
        {
            // Apply target.
            scrollTo(0.0, targetPosition);
            return;
        }

        // Filtered position.
        currentPosition = (parseFloat(currentPosition) * (1.0 - filter)) + (parseFloat(targetPosition) * filter);

        // Apply target.
        scrollTo(0.0, Math.round(currentPosition));

        // Schedule next tick.
        setTimeout("EPPZScrollTo.scrollVerticalTickToPosition("+currentPosition+", "+targetPosition+")", (1000 / fps));
    },

    /**
     * For public use.
     *
     * @param id The id of the element to scroll to.
     * @param padding Top padding to apply above element.
     */
    scrollVerticalToElementById: function(id, padding)
    {
        var element = document.getElementById(id);
        if (element == null)
        {
            console.warn('Cannot find element with id \''+id+'\'.');
            return;
        }

        var targetPosition = this.documentVerticalScrollPosition() + this.elementVerticalClientPositionById(id) - padding;
        var currentPosition = this.documentVerticalScrollPosition();

        // Clamp.
        var maximumScrollPosition = this.documentMaximumScrollPosition();
        if (targetPosition > maximumScrollPosition) targetPosition = maximumScrollPosition;

        // Start animation.
        this.scrollVerticalTickToPosition(currentPosition, targetPosition);
    }
};
Geri Borbás
  • 15,810
  • 18
  • 109
  • 172
  • @codeWithMe Yap, it is more like an iOS-like code, where actual quantity does not matter, so you can go ahead and name everything after what it does / contains. I prefer that over shortness. – Geri Borbás Dec 22 '18 at 19:38
2

Similar to @caveman's solution

const element = document.getElementById('theelementsid');

if (element) {
    window.scroll({
        top: element.scrollTop,
        behavior: 'smooth',
    }) 
}
Excellence Ilesanmi
  • 3,295
  • 1
  • 18
  • 17
2

A method i often use to scroll a container to its contents.

/**
@param {HTMLElement} container : element scrolled.
@param {HTMLElement} target : element where to scroll.
@param {number} [offset] : scroll back by offset
*/
var scrollAt=function(container,target,offset){
    if(container.contains(target)){
        var ofs=[0,0];
        var tmp=target;
        while (tmp!==container) {
            ofs[0]+=tmp.offsetWidth;
            ofs[1]+=tmp.offsetHeight;
            tmp=tmp.parentNode;
        }
        container.scrollTop = Math.max(0,ofs[1]-(typeof(offset)==='number'?offset:0));
    }else{
        throw('scrollAt Error: target not found in container');
    }
};

if your whish to override globally, you could also do :

HTMLElement.prototype.scrollAt=function(target,offset){
    if(this.contains(target)){
        var ofs=[0,0];
        var tmp=target;
        while (tmp!==this) {
            ofs[0]+=tmp.offsetWidth;
            ofs[1]+=tmp.offsetHeight;
            tmp=tmp.parentNode;
        }
        container.scrollTop = Math.max(0,ofs[1]-(typeof(offset)==='number'?offset:0));
    }else{
        throw('scrollAt Error: target not found in container');
    }
};
yorg
  • 600
  • 5
  • 7
2

If you simply want to scroll to the bottom of a list that is inside a div, you can do this.

<body>

<div class="container">
    <div class="box">1</div>
    <div class="box">2</div>
    <div class="box">3</div>
    <div class="box">4</div>
    <div class="box">5</div>
    <div class="box">6</div>
    <div class="box">7</div>
    <div class="box">8</div>
    <div class="box">9</div> 
</div>
<button>Scroll To</button>

    <script> 
        const btn = document.querySelector("button");
        const container = document.querySelector(".container"); 
        btn.addEventListener("click",()=>{
        const toplast = document.querySelector(".container").lastElementChild;
        toplast.scrollIntoView();
    })
    </script>
</body> 

example output

2

JS:

document.getElementById('targetid').scrollIntoView({behavior: 'smooth'});

USE with inline HTML :

<p class="text-notification">Some Notification <span style="color:blue;cursor:pointer;" onClick="document.getElementById('target').scrollIntoView({behavior: 'smooth'});">Go to target<span></p>
                        
infomasud
  • 2,263
  • 1
  • 18
  • 12
1

Focus can be set on interactive elements only... Div only represent a logical section of the page.

Perhaps you can set the borders around div or change it's color to simulate a focus. And yes Visiblity is not focus.

S M Kamran
  • 4,423
  • 7
  • 25
  • 35
1

Due to behavior "smooth" doesn't work in Safari, Safari ios, Explorer. I usually write a simple function utilizing requestAnimationFrame

(function(){
    var start;
    var startPos = 0;

    //Navigation scroll page to element
    function scrollTo(timestamp, targetTop){
      if(!start) start = timestamp
      var runtime = timestamp - start
      var progress = Math.min(runtime / 700, 1)

      window.scroll(0, startPos + (targetTop * progress) )

      if(progress >= 1){
        return;
      }else {
        requestAnimationFrame(function(timestamp){
            scrollTo(timestamp, targetTop)
        })
      }
   };

  navElement.addEventListener('click', function(e){

    var target = e.target  //or this 
    var targetTop = _(target).getBoundingClientRect().top
    startPos = window.scrollY

    requestAnimationFrame(function(timestamp){
        scrollTo(timestamp, targetTop)
    })
  }

})();
Brad Vanderbush
  • 173
  • 1
  • 13
0

After looking around a lot, this is what finally worked for me:

  1. Find/locate div in your dom which has scroll bar. For me, it looked like this : "div class="table_body table_body_div" scroll_top="0" scroll_left="0" style="width: 1263px; height: 499px;"

  2. I located it with this xpath : //div[@class='table_body table_body_div']

  3. Used JavaScript to execute scrolling like this : (JavascriptExecutor) driver).executeScript("arguments[0].scrollLeft = arguments[1];",element,2000);

2000 is the no of pixels I wanted to scroll towards the right. Use scrollTop instead of scrollLeft if you want to scroll your div down.

Note : I tried using scrollIntoView but it didn't work properly because my webpage had multiple divs. It will work if you have only one main window where focus lies. This is the best solution I have come across if you don't want to use jQuery which I didn't want to.

0

I think that if you add a tabindex to your div, it will be able to get focus:

<div class="divFirst" tabindex="-1">
</div>

I don't think it's valid though, tabindex can be applied only to a, area, button, input, object, select, and textarea. But give it a try.

Robin
  • 21,667
  • 10
  • 62
  • 85
  • 1
    In HTML5 `tabindex` is a "core attribute", which are "global attributes" (attributes that are common to all elements in the HTML language). See http://www.w3.org/TR/2011/WD-html-markup-20110113/global-attributes.html – Oriol Mar 23 '13 at 21:52
0

You can't focus on a div. You can only focus on an input element in that div. Also, you need to use element.focus() instead of display()

Andrey
  • 20,487
  • 26
  • 108
  • 176
  • 2
    You can make a `
    ` focusable if using the `tabindex` attribute. See http://dev.w3.org/html5/spec-author-view/editing.html#attr-tabindex
    – Oriol Mar 23 '13 at 21:54
-1

In case you want to use html, you could just use this:

a href="samplewebsite.com/subdivision.html#id

and make it an html link to the specific element id. Its basically getElementById html version.

Florin Pop
  • 5,105
  • 3
  • 25
  • 58
-4

try this function

function navigate(divId) {
$j('html, body').animate({ scrollTop: $j("#"+divId).offset().top }, 1500);
}

Pass the div id as parameter it will work I am using it already