Offset scroll anchor in HTML with Bootstrap 4 fixed navbar

前端 未结 5 551
孤独总比滥情好
孤独总比滥情好 2020-12-29 06:17

So, I have this single page that consists of a few sections. Users can go to these sections by scrolling themselves or clicking in the navbar (a href with anchor). Due to th

相关标签:
5条回答
  • 2020-12-29 06:56

    Usually when using a sticky header like that you’ll want to find the height of your navbar and offset the entire view accordingly. Something like

    body {
      margin-top:2rem;
    }
    

    Your other option would be to use JavaScript.

    0 讨论(0)
  • 2020-12-29 07:00

    I like to dynamically offset the height header (or navbar) like this:

    $('.nav-link').click(function(e){
        let divCoords = $(e.target.hash).offset();
        let height = $('header').height();
        e.preventDefault();
        window.scrollTo({
        left: divCoords.left, 
        top: divCoords.top - height,
        behavior: 'smooth'
        });
    });
    
    0 讨论(0)
  • 2020-12-29 07:09

    This solution adds a padding and removes the gap by a negative margin at the top. This worked best for me.

    section {
        padding-top: 56px;
        margin-top: -56px;
    }
    

    .offset {
        height: 54px;
    }
    
    /* START SNIPPET */
    section {
        padding-top: 56px;
        margin-top: -56px;
    }
    /* END SNIPPET */
    
    #section1 p, #section3 p {
        background-color: #ffffd;
    }
    #section2 p, #section4 p {
        background-color: #ccc;
    }
    p {
        min-height: 15rem;
    }
    <!doctype html>
    <html lang="en">
      <head>
        <!-- Required meta tags -->
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    
        <!-- Bootstrap CSS -->
        <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
    
      </head>
      <body>
     <nav class="navbar navbar-expand-md navbar-dark bg-dark fixed-top">
          <a class="navbar-brand" href="#">Navbar</a>
          <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarsExampleDefault" aria-controls="navbarsExampleDefault" aria-expanded="false" aria-label="Toggle navigation">
            <span class="navbar-toggler-icon"></span>
          </button>
    
          <div class="collapse navbar-collapse" id="navbarsExampleDefault">
            <ul class="navbar-nav mr-auto">
              <li class="nav-item">
                <a class="nav-link" href="#section1">Section 1</a>
              </li>
              <li class="nav-item">
                <a class="nav-link" href="#section2">Section 2</a>
              </li>
              <li class="nav-item">
                <a class="nav-link" href="#section3">Section 3</a>
              </li>
              <li class="nav-item">
                <a class="nav-link" href="#section4">Section 4</a>
              </li>
            </ul>
          </div>
        </nav>
     
      <div class="container">
        <div class="offset col-12"></div>
        <section id="section1" class="row">
          <p class="col-12">
            Section 1
          </p>
        </section>
        <section id="section2" class="row">
          <p class="col-12">
            Section 2
          </p>
        </section>
        <section id="section3" class="row">
          <p class="col-12">
            Section 3
          </p>
        </section>
        <section id="section4" class="row">
          <p class="col-12">
            Section 4
          </p>
        </section>
      </div>
     
      <!-- jQuery first, then Popper.js, then Bootstrap JS -->
      <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
      <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
      <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
    </body>
    </html>

    0 讨论(0)
  • 2020-12-29 07:13

    There are a few different ways to solve it, but I think the best way is to put a hidden pseudo element ::before each section. This is a CSS only solution, no JS or jQuery...

    section:before {
        height: 54px;
        content: "";
        display:block;
    }
    

    https://www.codeply.com/go/J7ryJWF5fr

    That will put the space needed to account for the fixed-top Navbar. You'll also want to remove the margin-top offset for #section1 since this method will work consistently for all sections and allow the scrollspy to work.


    Related
    How do I add a data-offset to a Bootstrap 4 fixed-top responsive navbar?
    Href Jump with Bootstrap Sticky Navbar

    0 讨论(0)
  • 2020-12-29 07:13

    you can use jQuery to override the default behavior so you don't have to change the layout ( margin, padding .. etc.)

      var divId;
    
      $('.nav-link').click(function(){    
        divId = $(this).attr('href');
         $('html, body').animate({
          scrollTop: $(divId).offset().top - 54
        }, 100);
      });
    

    https://codepen.io/anon/pen/NYRvaL

    0 讨论(0)
提交回复
热议问题