admin管理员组

文章数量:1414628

I have a webpage with a sticky header that I'm attempting to implement smooth scrolling to anchor tags for navigation. When I click on the navigation link to the section I want to go scrollTop: href.offset().top - 100 does not appear to work correctly. If I click the link again after the webpage has navigated to that section, I can see the page scroll, but then it bounces back to the top. Any idea what is going on? I'm using Microsoft Edge (Yeah, I know ...).

HTML

<!DOCTYPE HTML>
<html lang="en">
<head></head>
<body id="home">
    <nav><a href="#section1">Section #1</a></nav>
    <main>
        <!-- INSERT A BUNCH OF <BR> TAGS -->
        <h2 id="section1">section1</h2>
        <!-- INSERT A BUNCH OF <BR> TAGS -->
    </main>
</body>
</html>

CSS

nav {
    position:fixed;
    padding:4px;
border:2px solid #000;
width:100%;
    line-height:2.25em;
    background-color:yellow;
}

h2 {
    padding:4px;
    border:1px solid #000;
    width:100%;
    line-height:100px;
    background-color:red;
    }

jQuery

$(document).ready(function() {

    $('a[href*="#"]').click(function(event) {

        var href = $(this.hash);

        if (href.length) {
            event.preventDefault();
            $('html, body').animate({
                scrollTop: href.offset().top - 100
            }, 750, function() {
                location.hash = href.attr('id');
            });     
        }
    });
});

JSFiddle

EDIT:

I understand that setting a <div> element to display:fixed removes it from the flow of the page, which is what I believe is causing the issues. Is there a work around for this?

I have a webpage with a sticky header that I'm attempting to implement smooth scrolling to anchor tags for navigation. When I click on the navigation link to the section I want to go scrollTop: href.offset().top - 100 does not appear to work correctly. If I click the link again after the webpage has navigated to that section, I can see the page scroll, but then it bounces back to the top. Any idea what is going on? I'm using Microsoft Edge (Yeah, I know ...).

HTML

<!DOCTYPE HTML>
<html lang="en">
<head></head>
<body id="home">
    <nav><a href="#section1">Section #1</a></nav>
    <main>
        <!-- INSERT A BUNCH OF <BR> TAGS -->
        <h2 id="section1">section1</h2>
        <!-- INSERT A BUNCH OF <BR> TAGS -->
    </main>
</body>
</html>

CSS

nav {
    position:fixed;
    padding:4px;
border:2px solid #000;
width:100%;
    line-height:2.25em;
    background-color:yellow;
}

h2 {
    padding:4px;
    border:1px solid #000;
    width:100%;
    line-height:100px;
    background-color:red;
    }

jQuery

$(document).ready(function() {

    $('a[href*="#"]').click(function(event) {

        var href = $(this.hash);

        if (href.length) {
            event.preventDefault();
            $('html, body').animate({
                scrollTop: href.offset().top - 100
            }, 750, function() {
                location.hash = href.attr('id');
            });     
        }
    });
});

JSFiddle

EDIT:

I understand that setting a <div> element to display:fixed removes it from the flow of the page, which is what I believe is causing the issues. Is there a work around for this?

Share Improve this question edited Sep 13, 2018 at 22:26 artomason asked Sep 13, 2018 at 21:37 artomasonartomason 4,0336 gold badges28 silver badges45 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 4

EDIT:

Edge and Firefox were not cooperating with initial approach to modify hashchange behavior, so this edit simply removes the window.location.hash step to prevent the jump after the animation. However, this is not ideal because it prevents the default hash location behavior.

$(document).ready(function() {
  $('a[href*="#"]').on('click', (event) => {
    const hash = event.currentTarget.hash;
    if (hash) {
      event.preventDefault();
      $('html, body').animate({scrollTop: $(hash).offset().top - 100}, 750);
    }
  });
});
nav {
  position: fixed;
  padding: 4px;
  border: 2px solid #000;
  width: 100%;
  line-height: 2.25em;
  background-color: yellow;
}

h2 {
  padding: 4px;
  border: 1px solid #000;
  width: 100%;
  line-height: 100px;
  background-color: red;
}
<!DOCTYPE HTML>
<html lang="en">
  <head>
    <script src="https://ajax.googleapis./ajax/libs/jquery/2.1.1/jquery.min.js"></script>
  </head>
  <body id="home">
    <!-- Navigation -->
    <nav><a href="#section1">Section #1</a></nav>
    <!-- Main Content -->
    <main>
      <br>
      <br>
      <br>
      <br>
      <br>
      <br>
      <br>
      <br>
      <br>
      <br>
      <br>
      <br>
      <br>
      <br>
      <br>
      <br>
      <br>
      <br>
      <br>
      <br>
      <h2 id="section1">section1</h2>
      <br>
      <br>
      <br>
      <br>
      <br>
      <br>
      <br>
      <br>
      <br>
      <br>
      <br>
      <br>
      <br>
      <br>
      <br>
      <br>
      <br>
      <br>
      <br>
      <br>
    </main>
  </body>
</html>

ORIGINAL:

I think location.hash causes the scroll to jump to the top after the scrollTop animation has pleted. You can modify the hashchange event to stop the scroll at the same distance above your anchors to eliminate the jump.

$(document).ready(function() {
  $(window).on('hashchange', function() {
    window.scrollTo(window.scrollX, window.scrollY - 100);
  });
  
  $('a[href*="#"]').on('click', (event) => {
    const hash = event.currentTarget.hash;
    if (hash) {
      event.preventDefault();
      $('html, body').animate({
        scrollTop: $(hash).offset().top - 100
      }, 750, function() {
        window.location.hash = hash;
      });
    }
  });
});

As it was suggested before, Microsoft Edge does not appear to properly support the .hash feature without causing some ill effects such as the rebounding of the smooth scroll feature. In order to work around this, I decided to use pushState for browsers that supported it, which achieved the desired effect.

HTML

<!DOCTYPE HTML>
<html lang="en">
<head></head>
<body id="home">
    <nav><a href="#section1">Section #1</a></nav>
    <main>
        <!-- INSERT A BUNCH OF <BR> TAGS -->
        <h2 id="section1">section1</h2>
        <!-- INSERT A BUNCH OF <BR> TAGS -->
    </main>
</body>
</html>

CSS

nav {
    position: fixed;
    padding: 4px;
    border: 2px solid #000;
    width: 100%;
    line-height: 2.25em;
    background-color: yellow;
}

h2 {
    padding: 4px;
    border: 1px solid #000;
    width: 100%;
    line-height: 100px;
    background-color: red;
}

JAVASCRIPT

$('a[href*="#"]').click(function(event) {

    var href = $(this.hash);

    if (href.length) {
        event.preventDefault();
        $('html, body').animate({
            scrollTop: href.offset().top - 100
        }, 750, function() {
            if (history.pushState) {
                history.pushState(null, null, 'index.html#' + href.attr('id'));
            } else {
                location.hash = href.attr('id');
            }
        });     
    }
});

I was not able to figure out how to dynamically pull the calling file name, for example index.html or main.html to dynamically generate the hashed URL so that will have to be updated per page. Otherwise, this works exactly how I had expected. Please see the JSFiddle implementation for a working example.

本文标签: javascriptJQuery Smooth Scroll to Anchor with Sticky Navigation BarStack Overflow