I'm making a responsive site using Bootstrap and it contains accordions with a large amount of text, when you read to the bottom and click the next accordion, the large amount of text is collapsed and I'm left at the bottom of the page.
I found this useful code from Bootstrap accordion scroll to top of active panel heading but it scrolls to the top of all the accordions, not the specific one that is open.
$(function () { $('#accordion').on('shown.bs.collapse', function (e) { var offset = $('.panel.panel-default > .panel-collapse.in').offset(); if(offset) { $('html,body').animate({ scrollTop: $('.panel-heading').offset().top -20 }, 500); } }); });
How can this code be modified to scroll to the top of the currently active accordion?
<div class="panel-group custom-padding no-sides" id="accordion"> <div class="panel panel-default"> <a data-toggle="collapse" data-parent="#accordion" href="#collapse1"> <div class="panel-heading custom-padding"> <h4 class="panel-title text-uppercase">Short synopsis <i class="fa fa-chevron-down pull-right"></i></h4> </div> </a> <div id="collapse1" class="panel-collapse collapse"> <div class="panel-body"> <p id="game-deck"></p> </div> </div> </div> <div class="panel panel-default"> <a data-toggle="collapse" data-parent="#accordion" href="#collapse2"> <div class="panel-heading custom-padding"> <h4 class="panel-title text-uppercase">Concepts <i class="fa fa-chevron-down pull-right"></i></h4> </div> </a> <div id="collapse2" class="panel-collapse collapse"> <div class="panel-body"> <ul class="whatever" id="game-concepts"></ul> </div> </div> </div> <div class="panel panel-default"> <a data-toggle="collapse" data-parent="#accordion" href="#collapse3"> <div class="panel-heading custom-padding"> <h4 class="panel-title text-uppercase">Themes <i class="fa fa-chevron-down pull-right"></i></h4> </div> </a> <div id="collapse3" class="panel-collapse collapse"> <div class="panel-body" id="game-themes"></div> </div> </div> <div class="panel panel-default"> <a data-toggle="collapse" data-parent="#accordion" href="#collapse4"> <div class="panel-heading custom-padding"> <h4 class="panel-title text-uppercase">Notable locations<i class="fa fa-chevron-down pull-right"></i></h4> </div> </a> <div id="collapse4" class="panel-collapse collapse"> <div class="panel-body" id="game-locations"></div> </div> </div> <div class="panel panel-default"> <a data-toggle="collapse" data-parent="#accordion" href="#collapse5"> <div class="panel-heading custom-padding"> <h4 class="panel-title text-uppercase">Notable characters<i class="fa fa-chevron-down pull-right"></i></h4> </div> </a> <div id="collapse5" class="panel-collapse collapse"> <div class="panel-body" id="game-characters"></div> </div> </div> <div class="panel panel-default"> <a data-toggle="collapse" data-parent="#accordion" href="#collapse6"> <div class="panel-heading custom-padding"> <h4 class="panel-title text-uppercase">Full description <i class="fa fa-chevron-down pull-right"></i></h4> </div> </a> <div id="collapse6" class="panel-collapse collapse"> <div class="panel-body" id="game-description"></div> </div> </div> </div>
Always open Omit the data-bs-parent attribute on each .accordion-collapse to make accordion items stay open when another item is opened.
I've found that adding an href="#0" helps resolve this issue.
To create an accordion that is collapsed by default, we need to set the 'active' property of the jQuery Accordion as false. Syntax: $("#demoAccordion"). accordion({ collapsible: true, active: false});
The Bootstrap accordion is a component that organizes content within collapsable items. Accordion allows the display of only one collapsed item at a time. Accordions can toggle through a number of text blocks with a single click, and that greatly enhances the UX of your project.
You can animate the scroll by getting the top of the 'target element' and then calling animate on the body..
$('html, body').animate({ scrollTop: $("#target-element").offset().top }, 1000);
modifying it to be something like this will help you achieve what you are after
$('.panel-collapse').on('shown.bs.collapse', function (e) { var $panel = $(this).closest('.panel'); $('html,body').animate({ scrollTop: $panel.offset().top }, 500); });
source: http://www.abeautifulsite.net/smoothly-scroll-to-an-element-without-a-jquery-plugin-2/
complementary fiddle: https://jsfiddle.net/hjugdwbp/
Edit: 2018-05-25
Using the accordion example at: https://getbootstrap.com/docs/4.0/components/collapse/#accordion-example I have modified the code to support cards.
$('.collapse').on('shown.bs.collapse', function(e) { var $card = $(this).closest('.card'); $('html,body').animate({ scrollTop: $card.offset().top }, 500); });
Fiddle: https://jsfiddle.net/agpkc4v2/1/
Edit: 2019-07-18
https://jsfiddle.net/erutfgvn/
$('.panel-collapse').on('show.bs.collapse', function(e) { var $panel = $(this).closest('.panel'); var $open = $(this).closest('.panel-group').find('.panel-collapse.in'); var additionalOffset = 0; if($panel.prevAll().filter($open.closest('.panel')).length !== 0) { additionalOffset = $open.height(); } $('html,body').animate({ scrollTop: $panel.offset().top - additionalOffset }, 500); });
https://jsfiddle.net/9p7f0hut/
$('.collapse').on('show.bs.collapse', function(e) { var $card = $(this).closest('.card'); var $open = $($(this).data('parent')).find('.collapse.show'); var additionalOffset = 0; if($card.prevAll().filter($open.closest('.card')).length !== 0) { additionalOffset = $open.height(); } $('html,body').animate({ scrollTop: $card.offset().top - additionalOffset }, 500); });
Edit: 2021-04-20
https://jsfiddle.net/hLzg0n2y/2/
$('.collapse').on('shown.bs.collapse', function(e) { var $card = $(this).closest('.accordion-item'); var $open = $($(this).data('parent')).find('.collapse.show'); var additionalOffset = 0; if($card.prevAll().filter($open.closest('.accordion-item')).length !== 0) { additionalOffset = $open.height(); } $('html,body').animate({ scrollTop: $card.offset().top - additionalOffset }, 500); });
Update 2021
As of Bootstrap 5, jQuery is no longer required. Here is a vanilla JavaScript solution of scrolling to the top of the open accordion item...
const accordionItems = document.querySelectorAll('.accordion-collapse') const acc = document.getElementById('accordionExample') accordionItems.forEach((el)=>{ el.addEventListener('shown.bs.collapse',(e)=>{ var scrollOffset = acc.scrollTop + el.parentNode.offsetTop acc.scroll({ top: scrollOffset, left: 0, behavior: 'smooth' }) }) })
Demo
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With