user1299972
user1299972

Reputation:

Scrolling to a element inside a scrollable DIV with pure Javascript

I have a div that has overflow: scroll and I have some elements inside the DIV that are hidden. On click of a button on the page, I want to make the DIV scroll to a particular element inside the DIV.

How do I achieve this?

Upvotes: 43

Views: 76569

Answers (4)

piouson
piouson

Reputation: 4565

You need a ref to the div you wish to scroll to inner-div and a ref to the scrollable div scrollable-div:

const scrollToDiv = () => {
  const innerDivPos = document.getElementById('inner-div').offsetTop

  document
    .getElementById('scrollable-div')
    .scrollTo({ top: innerDivPos, behavior: 'smooth' })
}
<div id="scrollable-div" style="height:100px; overflow-y:auto;">
  <button type="button" style="margin-bottom:500px" onclick="scrollToDiv()">Scroll To Div</button>
  <div id="inner-div">Inner Div</div>
</div>

Upvotes: 2

bluefog
bluefog

Reputation: 1894

You need to read the offsetTop property of the div you need to scroll to and then set that offset to the scrollTop property of the container div. Bind this function the event you want to :

function scrollToElementD(){
    var topPos = document.getElementById('inner-element').offsetTop;
    document.getElementById('container').scrollTop = topPos-10;
}
div {
    height: 200px;
    width: 100px;
    border: 1px solid black;
    overflow: auto;
}

p {
    height: 80px;
    background: blue;
}
#inner-element {
    background: red;
}
<div id="container"><p>A</p><p>B</p><p>C</p><p id="inner-element">D</p><p>E</p><p>F</p></div>
<button onclick="scrollToElementD()">SCROLL TO D</button>

function scrollToElementD(){
  var topPos = document.getElementById('inner-element').offsetTop;
  document.getElementById('container').scrollTop = topPos-10;
}

Fiddle : http://jsfiddle.net/p3kar5bb/322/ (courtesy @rofrischmann)

Upvotes: 75

NoBrainer
NoBrainer

Reputation: 5950

Here's a simple pure JavaScript solution that works for a target Number (value for scrollTop), target DOM element, or some special String cases:

/**
 * target - target to scroll to (DOM element, scrollTop Number, 'top', or 'bottom'
 * containerEl - DOM element for the container with scrollbars
 */
var scrollToTarget = function(target, containerEl) {
    // Moved up here for readability:
    var isElement = target && target.nodeType === 1,
        isNumber = Object.prototype.toString.call(target) === '[object Number]';

    if (isElement) {
        containerEl.scrollTop = target.offsetTop;
    } else if (isNumber) {
        containerEl.scrollTop = target;
    } else if (target === 'bottom') {
        containerEl.scrollTop = containerEl.scrollHeight - containerEl.offsetHeight;
    } else if (target === 'top') {
        containerEl.scrollTop = 0;
    }
};

And here are some examples of usage:

// Scroll to the top
var scrollableDiv = document.getElementById('scrollable_div');
scrollToTarget('top', scrollableDiv);

or

// Scroll to 200px from the top
var scrollableDiv = document.getElementById('scrollable_div');
scrollToTarget(200, scrollableDiv);

or

// Scroll to targetElement
var scrollableDiv = document.getElementById('scrollable_div');
var targetElement= document.getElementById('target_element');
scrollToTarget(targetElement, scrollableDiv);

Upvotes: 9

Jay Cam
Jay Cam

Reputation: 101

Just improved it by setting a smooth auto scrolling inside a list contained in a div

https://codepen.io/rebosante/pen/eENYBv

var topPos = elem.offsetTop

document.getElementById('mybutton').onclick = function () {
   console.log('click')
  scrollTo(document.getElementById('container'), topPos-10, 600);   
}

function scrollTo(element, to, duration) {
    var start = element.scrollTop,
        change = to - start,
        currentTime = 0,
        increment = 20;

    var animateScroll = function(){        
        currentTime += increment;
        var val = Math.easeInOutQuad(currentTime, start, change, duration);
        element.scrollTop = val;
        if(currentTime < duration) {
            setTimeout(animateScroll, increment);
        }
    };
    animateScroll();
}

//t = current time
//b = start value
//c = change in value
//d = duration
Math.easeInOutQuad = function (t, b, c, d) {
    t /= d/2;
    if (t < 1) return c/2*t*t + b;
    t--;
    return -c/2 * (t*(t-2) - 1) + b;
};

I guess it may help someone :)

Upvotes: 10

Related Questions