20

I have a scrolling container with a hard coded height:

.scrollingContainer {
    overflow: scroll;
    height: 400px;
}

This scrolling container contains a list of items, when I click on the item I want to scroll the container so that the item clicked is at the top of the scrolling container.

$('.scrollingContainer li a').click( function(event) {
  var vpHeight = $('.scrollingContainer').height();
  var offset = $(this).offset();
  $('.scrollingContainer').animate({
    scrollTop: vpHeight - offset.top
  }, 500);
});

Above is what I have currently, I'm having trouble with the mathematical calculation I need to perform. Also I think the var offset value is incorrect as it seems to be getting the offset from the top of the page where I was hoping to get the offset value based on it's position in the scrolling container.

Any help appreciated!

CLiown
  • 13,665
  • 48
  • 124
  • 205
  • Here's a fiddle. Does it demonstrate the issue? It seems to work. http://jsfiddle.net/isherwood/LqQGR – isherwood Nov 20 '13 at 16:36
  • Yes, the problem being that I'm not really controlling what position it scrolls to. Also if I click twice it scrolls twice rather than sticking to the previously scrolled to position. – CLiown Nov 20 '13 at 16:38

2 Answers2

54

A variation of this answer does the trick:

var myContainer = $('.scrollingContainer')

$(myContainer).on('click', 'a', function () {
  var scrollTo = $(this);

  myContainer.animate({
    scrollTop: scrollTo.offset().top - myContainer.offset().top + myContainer.scrollTop()
  });
});

Fiddle demo

var myContainer = $('.scrollingContainer')

$(myContainer).on('click', 'a', function() {
  var scrollTo = $(this);
  myContainer.animate({
    scrollTop: scrollTo.offset().top - myContainer.offset().top + myContainer.scrollTop()
  });
});
body {
  padding: 50px;
}

.scrollingContainer {
  overflow: scroll;
  height: 400px;
  background-color: #eee;
}

a {
  font-size: 150%;
  color: red;
}
<p>This is a demo for <a target="_blank" href="http://stackoverflow.com/questions/20101059/scroll-element-into-view-in-scrollable-container/20102855#20102855">a question at Stack Overflow</a>.</p>
<div class="scrollingContainer">
  <p>Tropical Storm Keith, the eleventh tropical storm of the 1988 season, was the latest North Atlantic tropical cyclone in the calendar year to strike the Continental United States since the 1925 season. Keith developed out of a tropical wave in the Caribbean
    Sea on November 17 and reached a peak intensity of 70 mph (110 km/h) shortly before striking the northeastern tip of the Yucatán Peninsula. It turned northeastward in the Gulf of Mexico, and made landfall near Sarasota, Florida, on November 23. Keith
    became extratropical near Bermuda on November 24. The extratropical remnant persisted for two more days. Keith produced moderate to heavy rainfall in Honduras, Jamaica, and Cuba. Minimal damage was reported in Mexico. The last of four named North
    Atlantic hurricanes to hit the United States during the season, <a href="#">click hereabouts</a>, rough storm surge, and gusty winds across central Florida. Overall damage was fairly minor but widespread, totaling $7.3 million. Near the coast of Florida,
    damage occurred mainly from storm surge and beach erosion. Further inland there were floods, downed trees and power lines. No fatalities were reported.</p>

  <ul>
    <li><a href="#">click hereabouts</a></li>
    <li><a href="#">click hereabouts</a></li>
  </ul>
  <p>Tropical Storm Keith, the eleventh tropical storm of the 1988 season, was the latest North Atlantic tropical cyclone in the calendar year to strike the Continental United States since the 1925 season. Keith developed out of a tropical wave in the Caribbean
    Sea on November 17 and reached a peak intensity of 70 mph (110 km/h) shortly before striking the northeastern tip of the Yucatán Peninsula. It turned northeastward in the Gulf of Mexico, and made landfall near Sarasota, Florida, on November 23. Keith
    became extratropical near Bermuda on November 24. The extratropical remnant persisted for two more days. Keith produced moderate to heavy rainfall in Honduras, Jamaica, and Cuba. Minimal damage was reported in Mexico. The last of four named North
    Atlantic hurricanes to hit the United States during the season, Keith produced moderate rainfall, rough storm surge, and gusty winds across central Florida. Overall damage was fairly minor but widespread, totaling $7.3 million. Near the coast of Florida,
    damage occurred mainly from storm surge and beach erosion. Further inland there were floods, downed trees and power lines. No fatalities were reported.</p>
  <p>Tropical Storm Keith, the eleventh tropical storm of the 1988 season, was the latest North Atlantic tropical cyclone in the calendar year to strike the Continental United States since the 1925 season. Keith developed out of a tropical wave in the Caribbean
    Sea on November 17 and reached a peak intensity of 70 mph (110 km/h) shortly before striking the northeastern tip of the Yucatán Peninsula. It turned northeastward in the Gulf of Mexico, and made landfall near Sarasota, Florida, on November 23. Keith
    became extratropical near Bermuda on November 24. The extratropical remnant persisted for two more days. Keith produced moderate to heavy rainfall in Honduras, Jamaica, and Cuba. Minimal damage was reported in Mexico. The last of four named North
    Atlantic hurricanes to hit the United States during the season, Keith produced moderate rainfall, rough storm surge, and gusty winds across central Florida. Overall damage was fairly minor but widespread, totaling $7.3 million. Near the coast of Florida,
    damage occurred mainly from storm surge and beach erosion. Further inland there were floods, downed trees and power lines. No fatalities were reported.</p>
  <p>Tropical Storm Keith, the eleventh tropical storm of the 1988 season, was the latest North Atlantic tropical cyclone in the calendar year to strike the Continental United States since the 1925 season. Keith developed out of a tropical wave in the Caribbean
    Sea on November 17 and reached a peak intensity of 70 mph (110 km/h) shortly before striking the northeastern tip of the Yucatán Peninsula. It turned northeastward in the Gulf of Mexico, and made landfall near Sarasota, Florida, on November 23. Keith
    became extratropical near Bermuda on November 24. The extratropical remnant persisted for two more days. Keith produced moderate to heavy rainfall in Honduras, Jamaica, and Cuba. Minimal damage was reported in Mexico. The last of four named North
    Atlantic hurricanes to hit the United States during the season, Keith produced moderate rainfall, rough storm surge, and gusty winds across central Florida. Overall damage was fairly minor but widespread, <a href="#">click hereabouts</a>. Near the
    coast of Florida, damage occurred mainly from storm surge and beach erosion. Further inland there were floods, downed trees and power lines. No fatalities were reported.</p>
  <p>Tropical Storm Keith, the eleventh tropical storm of the 1988 season, was the latest North Atlantic tropical cyclone in the calendar year to strike the Continental United States since the 1925 season. Keith developed out of a tropical wave in the Caribbean
    Sea on November 17 and reached a peak intensity of 70 mph (110 km/h) shortly before striking the northeastern tip of the Yucatán Peninsula. It turned northeastward in the Gulf of Mexico, and made landfall near Sarasota, Florida, on November 23. Keith
    became extratropical near Bermuda on November 24. The extratropical remnant persisted for two more days. Keith produced moderate to heavy rainfall in Honduras, Jamaica, and Cuba. Minimal damage was reported in Mexico. The last of four named North
    Atlantic hurricanes to hit the United States during the season, Keith produced moderate rainfall, rough storm surge, and gusty winds across central Florida. Overall damage was fairly minor but widespread, totaling $7.3 million. Near the coast of Florida,
    damage occurred mainly from storm surge and beach erosion. Further inland there were floods, downed trees and power lines. No fatalities were reported.</p>
  <p>Tropical Storm Keith, the eleventh tropical storm of the 1988 season, was the latest North Atlantic tropical cyclone in the calendar year to strike the Continental United States since the 1925 season. Keith developed out of a tropical wave in the Caribbean
    Sea on November 17 and reached a peak intensity of 70 mph (110 km/h) shortly before striking the northeastern tip of the Yucatán Peninsula. It turned northeastward in the Gulf of Mexico, and made landfall near Sarasota, Florida, on November 23. Keith
    became extratropical near Bermuda on November 24. The extratropical remnant persisted for two more days. Keith produced moderate to heavy rainfall in Honduras, Jamaica, and Cuba. Minimal damage was reported in Mexico. The last of four named North
    Atlantic hurricanes to hit the United States during the season, Keith produced moderate rainfall, rough storm surge, and gusty winds across central Florida. Overall damage was fairly minor but widespread, totaling $7.3 million. Near the coast of Florida,
    damage occurred mainly from storm surge and beach erosion. Further inland there were floods, downed trees and power lines. No fatalities were reported.</p>
</div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.1/jquery.min.js"></script>
isherwood
  • 58,414
  • 16
  • 114
  • 157
4

Here's a live example: http://jsfiddle.net/LqQGR/12/

You want to set your scrollTop to the element's position (the distance between the top of the container and the link) plus the current scrollTop (the distance between the top of the contained content and the current place it's visible.

Also: you need to set your scrollingContainer to position: relative so that it's the offset parent of the content within.

var $scrollingContainer = $('.scrollingContainer');

$scrollingContainer.on('click', 'a', function (event) {
    var scrollTop = $scrollingContainer.scrollTop();
    var link      = $(event.currentTarget);
    var position  = link.position();

    $scrollingContainer.animate({
        scrollTop: position.top + scrollTop
    }, 500);
});

By the way, my answer is superior to one in which you add click event listeners to all anchor tags individually. This only adds one listener, which is more performant. Read more about delegated events

isherwood
  • 58,414
  • 16
  • 114
  • 157
Nate
  • 4,718
  • 2
  • 25
  • 26