Just a quick note on that wonderfully neat trick of using scrollTop() to elegantly shuffle the page along to a page position, and why you may find that it's not working as you'd expected.

I'm something of a newbie-norris when it comes to jQuery, having only dipped my toe into its lukewarm waters in the past 6 months or so. As such, I'm continually making stupid mistakes learning as I go along, and discovering neat little dust-bunnies that I can roll up into a tight ball and keep in my pocket for later.

Over the weekend I was banging out what I assumed was a fairly simple script: I wanted a list that could be expanded and collapsed, and two links; one above the list that would do the standard hideToggle(); and another link at the top of the page that would scroll down to the list, then open it up like a delicate flower. This was where I ran into confusion like a fly at a windowpane (that is to say, repeatedly).

Here's my HTML:

<a href="#mylist" id="scrolltolist">Show the list</a>

<!-- Here's a whole ton of other page content. Y'know, for scrolling down and the like. -->

<a href="#mylist" id="showlist">Show/hide the list</a>

<ul id="mylist">
 <li>Lorem ipsum</li>
 <li>Dolor sit amit</li>
 <li>consectetaur adipisicing elit</li>
 <li>I can write Lorem ipsum</li>
 <li>From memory now</li>
</ul>

And here's the jQuery to go along with it:

 $(document).ready(function() {
  
  $('#scrolltolist').click(function () {
   $('body,html').animate({
    scrollTop: $("#mylist").offset().top
   }, 800);
   
   if ($('#mylist').is(':hidden')) {
    $('#mylist').slideToggle(800);
   }
   
   return false;
  });
  
  $('#showlist').click(function () {
   $('#mylist').slideToggle(800);
   
   return false;
  });
  
  $('#mylist').hide();
 });

Looks straightforward enough, right? Well, it doesn't work, and I spent a good 30 minutes scratching my head over precisely why not.

The key is down to two lines in the jQuery function. This one:

   $('body,html').animate({
    scrollTop: $("#mylist").offset().top
   }, 800);

...and this one:

   $('#mylist').hide();

The ul with the ID #mylist is initially hidden, and if I displayed the value of $('#mylist').offset().top when the page first loaded, I got a big fat zero. So: you can't scroll to an element which has been hidden! It seems ridiculously simple, but it's the tiniest things that make us want to chew our fists off in frustration.

All I did was wrap the list in a div with an ID and scroll to that instead. Problem solved! Here's the fixed code in full:

<a href="#mylist" id="scrolltolist">Show the list</a>

<!-- Here's a whole ton of other page content. Y'know, for scrolling down and the like. -->

<a href="#mylist" id="showlist">Show/hide the list</a>

<div id="mylistcontainer">
 <ul id="mylist">
  <li>Lorem ipsum</li>
  <li>Dolor sit amit</li>
  <li>consectetaur adipisicing elit</li>
  <li>I can write Lorem ipsum</li>
  <li>From memory now</li>
 </ul>
</div>
 $(document).ready(function() {
  
  $('#scrolltolist').click(function () {
   $('body,html').animate({
    scrollTop: $("#mylistcontainer").offset().top
   }, 800);
   
   if ($('#mylist').is(':hidden')) {
    $('#mylist').slideToggle(800);
   }
   
   return false;
  });
  
  $('#showlist').click(function () {
   $('#mylist').slideToggle(800);
   
   return false;
  });
  
  $('#mylist').hide();
 });

  • pedrosepulveda

    Hi there thanks for such a good behavior!

    i have added a .delay() between the scrolling and the toggle so the scroll function finish first then the toggle happen otherwise is way to fast and the toggle happens almost at the same time as the scroll.

    .$(‘#mylist’).delay(1000).slideToggle(800);

    the delay is in miliseconds… you can tweak the delay to make the interaction nicer

    p.