34

I have unexpected page scrolling when try to collapse or expand elements of the accordion. Maybe I just doing something wrong with bootstrap grid system? Here is example of page:

How can I avoid this irritative effect?
jsfiddle available https://jsfiddle.net/Lfwvtyms/1/

<body>
<!--default navbar here-->
<main>
    <h1>Long long long long long long header header header header header header lng lasd lewq j</h1>
    <div class="container">
        <div class="row">
            <div class="col-xs-12">
                <div id="task-list">
                    <div id="accordion" role="tablist" aria-multiselectable="true" class="panel-group">

                        <div class="panel panel-default">
                            <div id="headingOne" role="tab" class="panel-heading"><h4 class="panel-title"><a
                                    data-toggle="collapse" data-target="#collapseOne" href="#collapseOne"
                                    aria-expanded="true" aria-controls="collapseOne">First list</a></h4></div>
                            <div id="collapseOne" role="tabpanel" aria-labelledby="headingOne"
                                 class="panel-collapse collapse in">
                                <ul class="list-group">
                                    <li class="list-group-item">Item1</li>
                                    <li class="list-group-item">Item2</li>
                                    <li class="list-group-item">Item3</li>
                                </ul>
                            </div>
                        </div>

                        <div class="panel panel-default">
                            <div id="headingTwo" role="tab" class="panel-heading"><h4 class="panel-title"><a
                                    data-toggle="collapse" data-target="#collapseTwo" href="#collapseTwo"
                                    aria-expanded="true" aria-controls="collapseTwo">Another list</a></h4></div>
                            <div id="collapseTwo" role="tabpanel" aria-labelledby="headingTwo"
                                 class="panel-collapse collapse in">
                                <ul class="list-group">
                                    <li class="list-group-item">Item1</li>
                                    <li class="list-group-item">Item2</li>
                                    <li class="list-group-item">Item3</li>
                                </ul>
                            </div>
                        </div>

                    </div>
                </div>

                <div id="someDiv">
                    <div class="row">
                        <div class="col-xs-12">
                            <div id="dummy">Div with fixed height here</div>
                        </div>
                    </div>
                </div>

            </div>
        </div>
    </div>
</main>
<footer class="container-fluid">my footer here</footer>
</body>
Maksim Nesterenko
  • 5,661
  • 11
  • 57
  • 91

7 Answers7

31

I had same problem (jump to the top on click to the link which was triggering the collapse toggle) the href="#" was changed to href="javascript:void(0);" and it is working great (toggling collapse without any scrolling to the top)

Mi-Creativity
  • 9,554
  • 10
  • 38
  • 47
Paul
  • 461
  • 4
  • 7
27

Replace the href properties on the a elements to # rather than, for example, #collapseOne

instead of this:

<a data-toggle="collapse" data-target="#collapseTwo" href="#collapseTwo"
     aria-expanded="true" aria-controls="collapseTwo">

do this

<a data-toggle="collapse" data-target="#collapseTwo" href="#"
     aria-expanded="true" aria-controls="collapseTwo">
Diego López
  • 1,559
  • 1
  • 19
  • 27
  • 5
    This will lead to the page scrolling to the top. – MrUpsidown Nov 23 '15 at 15:41
  • @MrUpsidedown, try changing the href="#" to href="" this will avoid the scolling to the top – Diego López Nov 23 '15 at 18:23
  • 9
    @DiegoLópez, for me creating an empty `href=""` caused the page to reload. I've found that adding an `href="#0"` helps resolve this issue. This is because # by itself causes the page to scroll to top. An empty href isn't valid and will sometimes cause the page to reload. An #0 should not exist on the page, since IDs can't start with numbers. Therefore clicking a link to that ID does not cause a jump to anywhere. – Garconis Aug 02 '16 at 15:29
  • @Garconis I just confirmed your answer – Mark A Nov 01 '16 at 18:56
13

I had the same issue. It turns out the href causes the problem. If you don't want the page to scroll at all when you collapse/expand, which is what I wanted, then simply remove the href altogether. Leaving it as # still made the screen scroll to the top for me.

did not work for me:

<a data-toggle="collapse" data-target="#collapseOne" href="#SectionOne"></a>
<a data-toggle="collapse" data-target="#collapseOne" href="#"></a>

worked:

<a data-toggle="collapse" data-target="#collapseOne"></a>

See my update here: https://jsfiddle.net/Lfwvtyms/5/

Simmy
  • 188
  • 1
  • 9
  • 1
    This will change the cursor to text selection when over the link. – flipside Jan 11 '17 at 14:05
  • 2
    An 'a' tag without the 'href' attribute is considered invalid html. – Pedro Moreira Jun 17 '17 at 03:56
  • 1
    Old issue but just wanted to repute the comment about A without an href as being invalid. The w3 html 401 spec says: "Authors may also create an A element that specifies no anchors, i.e., that doesn't specify href, name, or id. Values for these attributes may be set at a later time through scripts." – CG Monroe Oct 05 '20 at 14:24
5

I had the same problem and I found my solution with this answer on another post.

Nothing else worked except for this tiny piece of Javascript added to my custom .js file. It smoothly brings the focus back to the selected panel title. The only thing I changed to suit my design was the distance to the top, on line 6.

https://stackoverflow.com/a/38180220/4844273

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

    var panel = $(this).find('.in');

    $('html, body').animate({
        scrollTop: panel.offset().top - 130
    }, 500);
});
Jonathan Marzullo
  • 6,879
  • 2
  • 40
  • 46
elarcoiris
  • 1,914
  • 4
  • 28
  • 30
4

Another option is to use buttons instead of anchor links, so that no href is triggered in the first place. For example, instead of the first <a>:

<button data-toggle="collapse" data-target="#collapseOne"
  aria-expanded="true" aria-controls="collapseOne">
  First list
</button>

There are lots of examples using <button> instead of <a> in this documentation.

jtenclay
  • 249
  • 4
  • 6
2

This would definitely work if you are out of options:

$('.panel-group').on('click', function(){
  $('html,body').stop();
});
NearHuscarl
  • 66,950
  • 18
  • 261
  • 230
Salvatore
  • 1,435
  • 1
  • 10
  • 21
1

You can override the click handler and use the preventDefault() method on the click event:

$('.aHandler').click( function(event) {
    event.preventDefault();
    ...
});

Where the 'aHandler' is a class on your 'a' tags: <a class="aHandler" ...>...</a>, or is any other valid jquery selector.

user2812481
  • 124
  • 5