268

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
  • 61,566
  • 21
  • 152
  • 187
C..
  • 5,859
  • 10
  • 29
  • 36
  • 1
    `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
  • 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
  • Focus as scrolling into view? – epascarello Feb 15 '11 at 18:07
  • 13
    [`el.scrollIntoView(true)`](https://developer.mozilla.org/en-US/docs/Web/API/Element.scrollIntoView) – Blazemonger Jun 09 '14 at 18:12

20 Answers20

423

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
  • 7,838
  • 5
  • 30
  • 35
  • 11
    @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
  • 4
    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` – The Red Pea 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
167

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
  • 160
  • 3
  • 13
Nikoloff
  • 3,762
  • 1
  • 16
  • 18
  • 15
    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? – Qian Chen 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
120

your question and the answers looks different. I don't know if I am mistaken, but for those who googles and reach here my answer would be the following:

  1. My answer on stackoverflow
  2. A similar question

My Answer explained:

here is a simple javascript for that

call this when you need to scroll the screen to an element which has id="yourSpecificElementId"

window.scroll(0,findPos(document.getElementById("yourSpecificElementId")));

ie. for the above question, if the intention is to scroll the screen to the div with id 'divFirst'

the code would be: window.scroll(0,findPos(document.getElementById("divFirst")));

and you need this function for the working:

//Finds y value of given object
function findPos(obj) {
    var curtop = 0;
    if (obj.offsetParent) {
        do {
            curtop += obj.offsetTop;
        } while (obj = obj.offsetParent);
    return [curtop];
    }
}

the screen will be scrolled to your specific element.

Community
  • 1
  • 1
AnhSirk Dasarp
  • 9,026
  • 6
  • 43
  • 54
  • 15
    This solution has the advantage of not messing with the visible URL in the navigation bar of the browser by adding MyID anchors. – Renaud Bompuis Oct 22 '13 at 09:47
  • 2
    Thank you, I feel like this should be the accepted answer sense it is java-script, not HTML like the current answer which wouldn't work for me, but this did! – Steve Byrne Jun 02 '14 at 12:52
  • That is, if it is the `window` you would like to scroll, not an overflow-ing viewing area – WebWanderer Feb 20 '15 at 21:11
  • 2
    Works after changing `[curtop]` to `curtop` at the end – goldylucks Jul 21 '19 at 15:48
  • 1
    If you dont want it to push this element to the very tip top of the page but instead prefer it to scroll so that the element is in the center of the screen, subtract `(window.screen.height/2)` from findPos – Albert Renshaw May 06 '20 at 03:04
79

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, Edge and 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
  • 1,874
  • 13
  • 17
  • 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` – goldylucks 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
26

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,452
  • 17
  • 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
16

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
  • 350
  • 3
  • 8
15

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

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

node.focus()

node.removeAttribute('tabindex')

ZhenyaUsenko
  • 333
  • 3
  • 7
  • 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
8

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
  • 78,650
  • 19
  • 129
  • 131
  • 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
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
  • 7,286
  • 4
  • 31
  • 32
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
  • 14,896
  • 16
  • 104
  • 167
  • @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
  • 2,905
  • 1
  • 17
  • 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
  • 572
  • 5
  • 7
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,278
  • 7
  • 24
  • 35
1

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,178
  • 10
  • 56
  • 83
  • 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
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
  • 167
  • 1
  • 11
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

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
  • 19,434
  • 24
  • 100
  • 171
  • 1
    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
  • 4,997
  • 3
  • 22
  • 57
-1

Jquery solution:

$("#divFirst")[0].scrollIntoView();
Saghachi
  • 703
  • 9
  • 15
-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