Igor Kromin |   Consultant. Coder. Blogger. Tinkerer. Gamer.

NOTE: This article is 3 years or older so its information may no longer be relevant. Read on at your own discretion! Comments for this article have automatically been locked, refer to the FAQ for more details.
I've recently discovered a problem in a website I've built where clicking a Bootstrap 3 accordion panel to expand it and show the content would erroneously scroll that panel off screen. This was happening because the content was being loaded dynamically via the show.bs.collapse event. After a bit of playing around with the implementation I found a way to scroll the panel, including its heading correctly to the top of the screen.

It turns out that I was using an incorrect event, I should have been using 'shown' instead of 'show', since the former is fired after the Bootstrap's CSS animation completes, the latter is fired as soon as the panel is opened i.e. during the collapse animation. I also needed to scroll to the panel heading.

These screenshots demonstrate the problem. I have a number of collapsed panels, when a panel is shown, I dynamically load its content, which can have a variable height, depending on the panel.
bstrapdynscroll1.png


If the panel was close to the top of the screen, once the dynamic content loaded, it would be shown incorrectly off-screen.
bstrapdynscroll2.png


Whereas, this is what should have been happening...the panel and its heading being shown at the top of the screen instead.
bstrapdynscroll3.png




This is how I solved it...the divId calculation is not shown here as that can be implementation specific, I also don't show the URL of the dynamic content I'm loading since that is not relevant to this example.
 JavaScript
$('#accordion').on('shown.bs.collapse', function(e){
divId = xxxx; // <-- works out the ID of the DIV to load into
$('#' + divId).load(xxxx); // <-- loads dynamic content once the panel is shown
// finds the panel heading element
scrlTo = $('#' + divId).closest('.panel').find('.panel-heading');
// scrolls the panel heading to the top of the window with a 6 pixel gap at the top
$('html,body').animate({ scrollTop: scrlTo.offset().top - 6 }, 50, 'swing');
});


For the above to work, I nest a div element with and ID inside my panel-body div, like this...I've simplified this slightly, my actual div has a loading animation and the ID is assigned dynamically using PHP.
 HTML
...
<div class="panel-body">
<div id="id1">Loading...</div>
...



So now whenever I click a panel heading to expand it, it's scrolled to the top as expected. There is a small delay while loading the dynamic content, but positioning happens before this content is loaded. The video below demonstrates this in action.



-i

Skip down to comments...
Hope you found this post useful...

...so please read on! I love writing articles that provide beneficial information, tips and examples to my readers. All information on my blog is provided free of charge and I encourage you to share it as you wish. There is a small favour I ask in return however - engage in comments below, provide feedback, and if you see mistakes let me know.

If you want to show additional support and help me pay for web hosting and domain name registration, donations, no matter how small, are always welcome!

Use of any information contained in this blog post/article is subject to this disclaimer.
 
comments powered by Disqus
Other posts you may like...