点击Bootstrap手风琴,如何滚动到活动(打开)手风琴的顶部?

32

我正在使用Bootstrap制作一个响应式网站,并且其中包含大量文本的手风琴。当你读到底部并单击下一个手风琴时,大量文本将被折叠起来,而我则留在页面底部。

我在Bootstrap手风琴滚动到活动面板标题的顶部找到了这个有用的代码,但是它会滚动到所有手风琴的顶部,而不是打开的特定手风琴的顶部。

JS

$(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); 
        }
    }); 
});

如何修改这段代码以使其滚动到当前正在使用的手风琴组件的顶部?

HTML

<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>
6个回答

86

您可以通过获取“目标元素”的顶部位置,然后在body上调用animate来使滚动动画化。

$('html, body').animate({
    scrollTop: $("#target-element").offset().top
}, 1000);

修改它为这样的格式将有助于您实现您想要的效果

$('.panel-collapse').on('shown.bs.collapse', function (e) {
    var $panel = $(this).closest('.panel');
    $('html,body').animate({
        scrollTop: $panel.offset().top
    }, 500); 
}); 

来源: http://www.abeautifulsite.net/smoothly-scroll-to-an-element-without-a-jquery-plugin-2/

补充示例: https://jsfiddle.net/hjugdwbp/


编辑: 2018-05-25

Bootstrap 4 示例

此处使用手风琴示例,我修改了代码以支持卡片。

$('.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

我让它更漂亮了...

Bootstrap 3

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);
});

Bootstrap 4

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);
});

编辑时间:2021-04-20

Bootstrap 5

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);
});

我无法想象在没有为每个面板编写一个具有唯一 ID 的不同函数的情况下,这将如何工作? - user3574766
谢谢,那非常有帮助。 - user3574766
它运行良好。如果必要,您可以偏移一些滚动条,在我的情况下是必要的。 - PC.
太棒了!如果需要添加一些偏移量,例如固定的导航栏,可以手动添加,比如 scrollTop: $card.offset().top - additionalOffset - 75 或者更酷的是动态获取。 - Jon
1
@JDW 我已经更新了答案。虽然不像其他的那么流畅,但它是可行的。我会继续改进流畅度。 - Michael Coxon
显示剩余7条评论

8

更新 2021

Bootstrap 5 开始,不再需要使用 jQuery。以下是一个使用原生 JavaScript 实现的滚动到打开的手风琴项目顶部的解决方案...

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'
        })
    })
})

演示


accordion-collapse可能是可选的。也许这样更好:accordionItems = acc.querySelectorAll('.collapse') - Arthur Shlain
2
window.scroll方法替换acc.scroll - Arthur Shlain

2

我正在处理一个需要相同功能的项目。我想到了以下代码。我添加了变量以便更清楚理解:

$('#accordion').on('shown.bs.collapse', function (e) {

var panelHeadingHeight = $('.panel-heading').height();
var animationSpeed = 500; // animation speed in milliseconds
var currentScrollbarPosition = $(document).scrollTop();
var topOfPanelContent = $(e.target).offset().top;

if ( currentScrollbarPosition >  topOfPanelContent - panelHeadingHeight) {
    $("html, body").animate({ scrollTop: topOfPanelContent - panelHeadingHeight }, animationSpeed);
}});

根据您的使用情况,我真的很喜欢这个答案。被接受的答案每次都会有效地滚动,而这个答案只有在您看不到面板/按钮触发器的顶部时才会滚动。在大多数情况下,这是更好的用户体验。需要注意一些小调整/事项:(1)在Safari / iPad上使用.scrollTop时要小心(2)如果您有一个粘性标题,您需要将其添加到正在进行的“减法”中。(3)在此示例中,您可能希望添加比panelHeadingHeight更多的内容,例如* 2,以便他们在按钮上方获得一些视觉空间。 - Bung

0

使用原生的 JavaScript 实现。

为具有accordion-collapse类的元素赋予唯一的id(collapse-{{uniqueId}})后:

let accordionItemsToBeFocused = document.querySelectorAll("[id^=collapse-]");

accordionItemsToBeFocused.forEach((el)=>{
    el.addEventListener('shown.bs.collapse',(e)=>{
        window.location.href = '#' + el.id
    })
})

0
$('.accordion-button').on("click",function(event){
    var accordion = $(this).parent().parent().parent();
    window.setTimeout(function(){
      $('body,html').stop().animate({ scrollTop: accordion[0].scrollHeight}, 1000);
    },100)
  }

当用户点击手风琴箭头按钮时,以上代码中会执行以下步骤:

1.将手风琴变量设置为具有“.accordion”类的父节点。

2.accordion[0].scrollHeight-查找已打开的手风琴的滚动高度。

3.使用animate选项,使用scrollTop将页面移动到手风琴的滚动高度。

4.为确保在手风琴打开后执行步骤2和3,setTimeout函数用于计时代码。如果在您的情况下手风琴主体更长,则可以相应地更改该值。当前在上述代码中为100。


1
请在您的代码中添加解释,以获得更完整和详细的答案。 - kennysliding

-1
let accordionItemsToBeFocused = document.querySelectorAll("[id^=collapse-]");
  accordionItemsToBeFocused.forEach((el)=>{
   el.addEventListener('shown.bs.collapse',(e)=>{
   document.querySelector('#'+ el.id).scrollIntoView({ behavior: 'smooth' }
  })
})

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接