Search code examples
bootstrap-5off-canvas-menu

Bootstrap Offcanvas navigation - don't reset background on close


I've got a long list of links in an offcanvas div. These are in the form because I want to use them to navigate a very long background page. (Effectively, it is a table of contents)

The offcanvas pops up happily. The navigation links work; jumping the background page to the correct position. Hurrah!

But... when you've selected and link and navigated the background page to a location and then close the offcanvas the background page resets to the top of the page! Argghh...

How can I keep the background page from resetting position, when I close the offcanvas?

Thanks for any help available.

div.head{
font-weight: bold;
margin-top: 10px;
}
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script>
<div class="btn-group btn-group-sm" role="group" aria-label="spec_tools">
    <a class="btn btn-outline-primary" data-bs-toggle="offcanvas" href="#offcanvasNav" role="button" aria-controls="offcanvasNav">Navigator</a>
</div>
    
<div class="offcanvas offcanvas-start" tabindex="-1" id="offcanvasNav" aria-labelledby="offcanvasNavLabel">
<div class="offcanvas-header">
<h5 class="offcanvas-title" id="offcanvasNavLabel">Navigator</h5>
<button type="button" class="btn-close text-reset" data-bs-dismiss="offcanvas" aria-label="Close"></button>
</div>
<div class="offcanvas-body">
<strong>
<div>
<a href="#item0">Item0</a>
</div>
</strong>
<div class="ms-2">
<a href="#item1">Item 1</a>
</div>
<div class="ms-2">
<a href="#item2">Item 2</a>
</div>

<div class="ms-2">
<a href="#item3">Item 3</a>
</div>

<div class="ms-2">
<a href="#item4">Item 4</a>
</div>

<div class="ms-2">
<a href="#item5">Item 5</a>
</div>
</div>
</div>

<!-- Page Content -->
<div class="head" id="item0">Item 0</div>
<div>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce finibus ullamcorper nunc eu luctus. Etiam congue placerat lorem, id congue massa ornare sed. Morbi imperdiet turpis eu urna semper tincidunt. Praesent ultrices mollis arcu vel elementum. Duis sollicitudin ultrices felis, nec vehicula massa congue in. Sed urna quam, sollicitudin ac felis et, ullamcorper dictum mauris. Morbi eu magna sit amet est placerat mollis sit amet at nisi. Phasellus viverra maximus posuere. Aenean et urna ac metus elementum pretium. Donec eu tortor id libero sollicitudin facilisis sit amet id nibh. Duis id eros tortor.</div>

<div class="head" id="item1">Item 1</div>
<div>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce finibus ullamcorper nunc eu luctus. Etiam congue placerat lorem, id congue massa ornare sed. Morbi imperdiet turpis eu urna semper tincidunt. Praesent ultrices mollis arcu vel elementum. Duis sollicitudin ultrices felis, nec vehicula massa congue in. Sed urna quam, sollicitudin ac felis et, ullamcorper dictum mauris. Morbi eu magna sit amet est placerat mollis sit amet at nisi. Phasellus viverra maximus posuere. Aenean et urna ac metus elementum pretium. Donec eu tortor id libero sollicitudin facilisis sit amet id nibh. Duis id eros tortor.</div>

<div class="head" id="item2">Item 2</div>
<div>Phasellus at efficitur orci. In imperdiet ut purus a semper. Mauris cursus ipsum vel finibus efficitur. Sed sit amet sem euismod, volutpat lacus ac, euismod justo. Pellentesque tincidunt justo in quam vulputate tincidunt. Curabitur porttitor felis arcu, et pellentesque odio malesuada quis. Aliquam hendrerit sapien tortor, eu ornare lorem laoreet interdum. Suspendisse velit lectus, sagittis eget ex nec, dictum finibus ex. Proin eget mollis nisl. Suspendisse porttitor placerat gravida. Vestibulum nec tempor eros, a congue ipsum. Ut est libero, viverra semper dapibus et, consectetur non risus. Cras at mauris pulvinar mauris accumsan ullamcorper. Aliquam nec ex libero. Suspendisse rhoncus erat sit amet tellus congue, sit amet sodales leo faucibus. Fusce risus diam, ullamcorper sit amet pulvinar eu, tempor vulputate eros.</div>

<div class="head" id="item3">Item 3</div>
<div>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce finibus ullamcorper nunc eu luctus. Etiam congue placerat lorem, id congue massa ornare sed. Morbi imperdiet turpis eu urna semper tincidunt. Praesent ultrices mollis arcu vel elementum. Duis sollicitudin ultrices felis, nec vehicula massa congue in. Sed urna quam, sollicitudin ac felis et, ullamcorper dictum mauris. Morbi eu magna sit amet est placerat mollis sit amet at nisi. Phasellus viverra maximus posuere. Aenean et urna ac metus elementum pretium. Donec eu tortor id libero sollicitudin facilisis sit amet id nibh. Duis id eros tortor.</div>

<div class="head" id="item4">Item 5</div>
<div>Phasellus at efficitur orci. In imperdiet ut purus a semper. Mauris cursus ipsum vel finibus efficitur. Sed sit amet sem euismod, volutpat lacus ac, euismod justo. Pellentesque tincidunt justo in quam vulputate tincidunt. Curabitur porttitor felis arcu, et pellentesque odio malesuada quis. Aliquam hendrerit sapien tortor, eu ornare lorem laoreet interdum. Suspendisse velit lectus, sagittis eget ex nec, dictum finibus ex. Proin eget mollis nisl. Suspendisse porttitor placerat gravida. Vestibulum nec tempor eros, a congue ipsum. Ut est libero, viverra semper dapibus et, consectetur non risus. Cras at mauris pulvinar mauris accumsan ullamcorper. Aliquam nec ex libero. Suspendisse rhoncus erat sit amet tellus congue, sit amet sodales leo faucibus. Fusce risus diam, ullamcorper sit amet pulvinar eu, tempor vulputate eros.</div>


Solution

  • Bootstrap is re-focusing and scrolling to the offcanvas trigger element when the offcanvas is closed. I've opened a bug report on this: https://github.com/twbs/bootstrap/issues/34447, however the behavior may be by-design.

    Workaround:

    Bootstrap currently checks to see if the trigger element is visible in the viewport when the offcanvas is hidden. Therefore, a workaround is to make the trigger element always visible on the page using fixed positioning...

    For example,

    <div class="offcanvas offcanvas-start" tabindex="-1" id="offcanvasNav" data-bs-scroll="true" aria-labelledby="offcanvasNavLabel">
        <div class="offcanvas-header">
            <h5 class="offcanvas-title" id="offcanvasNavLabel">Navigator</h5>
            <button type="button" class="btn-close text-reset" data-bs-dismiss="offcanvas" aria-label="Close" tabindex="-1"></button>
        </div>
        <div class="offcanvas-body">
            ...TOC nav
        </div>
    </div>
    <div class="container-fluid py-2">
        <div class="row">
            <div class="col-2">
                <!-- fixed position trigger always visible -->
                <button class="btn btn-outline-primary position-fixed" data-bs-toggle="offcanvas" data-bs-target="#offcanvasNav" role="button" id="btnTrigger" aria-controls="offcanvasNav">Navigator</button>
            </div>
            <div class="col">
                <div class="head" id="item0">Item 0</div>
                .. more page content
            </div>
        </div>
    </div>
    

    https://codeply.com/p/gALtKp3xd4