基于 scrollTop() 添加 class 并为导航栏使用位置粘性时出现问题

Issue when adding class based on scrollTop() and using position sticky for navbar

我正在尝试构建一个导航栏,其中的填充会随着用户开始滚动而缩小。缩小是通过简单地向滚动上的 header 元素添加 class 然后更改 CSS.

中的填充来完成的

我遇到的问题是,当我滚动到 50px 左右时,'shrink' class 添加到 toggleClass 卡在一个循环中,使导航栏在两者之间翻转 css属性真快。这可以通过将 'position: fixed' 应用于 header 元素而不是 'sticky' 来解决,但是在这种情况下我需要使用 'position:sticky'。

$(window).on("scroll touchmove", function() {
  $('header').toggleClass('shrink', $(document).scrollTop() > 50);
});
body {
  padding: 0;
  margin: 0;
}

header {
  background: red;
  position: sticky;
  top: 0;
  padding: 50px 0;
}

header.shrink {
  padding: 10px 0;
}

.nav-container {
  max-width: 1400px;
  margin: 0 auto;
  background: green;
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.logo {
  padding: 0;
  margin: 0;
  display: block;
}

nav ul {
  list-style: none;
  background: orange;
  display: flex;
}

main {
  max-width: 1400px;
  margin: 0 auto;
}

main .container {
  background: rgb(34, 193, 195);
  background: linear-gradient(180deg, rgba(34, 193, 195, 1) 0%, rgba(253, 187, 45, 1) 100%);
  min-height: 6000px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<header>
  <div class="nav-container">
    <div class="logo">
      Logo
    </div>
    <nav>
      <ul>
        <li>Home</li>
        <li>About</li>
        <li>Contact</li>
      </ul>
    </nav>
  </div>
</header>
<main>
  <div class="container">
    <h2>Content</h2>
  </div>
</main>

Click here for a codepen example

问题是你的元素的大小发生了变化,然后浏览器 re-calculates 滚动位置给你带来了很好的故障。

这是一个已知错误:chromium, bugzilla

更新:我发现的唯一“解决方案”是拥有一个永远不会改变大小的外部元素(在您的情况下为 header)。那个是粘性的,它的高度应该由 height + bottom margin 定义(这样它在文档中占据了正确的初始 space 并且不会触发重新计算。

$(window).on("scroll touchmove", function() {
  $('header').toggleClass('shrink', $(document).scrollTop() > 50);
});
body {
  padding: 0;
  margin: 0;
}

header {
  overflow-anchor: none;
  position: sticky;
  top: 0;
  height: 70px;
  margin-bottom:80px;
}

header.shrink .sticky-wrapper {
  padding: 10px 0;
}
.sticky-wrapper {
  background: red;
  padding: 50px 0;
  transition: padding 0.2s ease-in-out;
}

.nav-container {
  max-width: 1400px;
  margin: 0 auto;
  background: green;
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.logo {
  padding: 0;
  margin: 0;
  display: block;
}

nav ul {
  list-style: none;
  background: orange;
  display: flex;
}

main {
  max-width: 1400px;
  margin: 0 auto;
}

main .container {
  background: rgb(34, 193, 195);
  background: linear-gradient(180deg, rgba(34, 193, 195, 1) 0%, rgba(253, 187, 45, 1) 100%);
  min-height: 6000px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<header>
  <div class="sticky-wrapper">
    <div class="nav-container">
      <div class="logo">
        Logo
      </div>
      <nav>
        <ul>
          <li>Home</li>
          <li>About</li>
          <li>Contact</li>
        </ul>
      </nav>
    </div>
  </div>
</header>
<main>
  <div class="container">
    <h2>Content</h2>
  </div>
</main>