向下滚动后粘性标题

问题描述 投票:0回答:13

我在这个网站上看到了这个粘性标题: http://dunked.com/ (不再活跃,查看存档网站

当您向下滚动时,粘性标题会从顶部下降。

我看了代码,看起来确实很复杂。我只明白这个: 普通的标题是用 JS 克隆的,当你向下滚动页面时,它会从顶部开始动画。

javascript jquery header sticky
13个回答
62
投票

这是一个开始。基本上,我们在加载时复制标题,然后检查(使用

.scrollTop()
window.scrollY
)以查看用户何时滚动超出某个点(例如 200 像素)。然后我们只需切换一个类(在本例中为
.down
)即可将原始内容移至视图中。

最后我们需要做的就是将

transition: top 0.2s ease-in
应用于我们的克隆,以便当它处于
.down
状态时它会滑入视图。 Dunked 做得更好,但稍加尝试就可以轻松配置

CSS

header {
  position: relative;
  width: 100%;
  height: 60px;
}

header.clone {
  position: fixed;
  top: -65px;
  left: 0;
  right: 0;
  z-index: 999;
  transition: 0.2s top cubic-bezier(.3,.73,.3,.74);
}

body.down header.clone {
  top: 0;
}

两者都Vanilla JS(根据需要填充)

var sticky = {
  sticky_after: 200,
  init: function() {
    this.header = document.getElementsByTagName("header")[0];
    this.clone = this.header.cloneNode(true);
    this.clone.classList.add("clone");
    this.header.insertBefore(this.clone);
    this.scroll();
    this.events();
  },

  scroll: function() {
    if(window.scrollY > this.sticky_after) {
      document.body.classList.add("down");
    }
    else {
      document.body.classList.remove("down");
    }
  },

  events: function() {
    window.addEventListener("scroll", this.scroll.bind(this));
  }
};

document.addEventListener("DOMContentLoaded", sticky.init.bind(sticky));

jQuery

$(document).ready(function() {
  var $header = $("header"),
      $clone = $header.before($header.clone().addClass("clone"));

  $(window).on("scroll", function() {
    var fromTop = $("body").scrollTop();
    $('body').toggleClass("down", (fromTop > 200));
  });
});

新思考

虽然上面回答了OP最初的问题“Dunked如何实现这种效果?”,但我不推荐这种方法。对于初学者来说,复制整个顶部导航可能会非常昂贵,而且我们没有真正的理由不能使用原始导航(只需做一点工作)。

此外,Paul Irish 和其他人写过如何使用

translate()
制作动画比使用
top
制作动画更好。它不仅性能更高,而且还意味着您不需要知道元素的确切高度。上述解决方案将修改为以下(参见 JSFiddle)

header.clone {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  transform: translateY(-100%);
  transition: 0.2s transform cubic-bezier(.3,.73,.3,.74);
}

body.down header.clone {
  transform: translateY(0);
}

使用转换的唯一缺点是,虽然浏览器支持非常好,但您可能需要添加供应商前缀版本以最大限度地提高兼容性。


12
投票

这是一个JS小提琴http://jsfiddle.net/ke9kW/1/

正如其他人所说,将标题设置为固定,并以 display: none 开始

然后是 jQuery

$(window).scroll(function () {
  if ( $(this).scrollTop() > 200 && !$('header').hasClass('open') ) {
    $('header').addClass('open');
    $('header').slideDown();
   } else if ( $(this).scrollTop() <= 200 ) {
    $('header').removeClass('open');
    $('header').slideUp();
  }
});

其中 200 是您希望其向下移动的高度(以像素为单位)。添加开放类是为了允许我们运行 elseif 而不是仅运行 else,因此某些代码不必在每个滚动事件上运行,节省一点内存


2
投票

这里有很多 jQuery 插件,将有助于实现类似的效果:http://jquery-plugins.net/tag/sticky-scroll


1
投票

我使用 jQuery .scroll() 函数使用scrollTop 来跟踪工具栏滚动值的事件。然后,我使用条件来确定它是否大于我想要替换的值。在下面的示例中,它是“结果”。如果该值为 true,则结果标签添加一个类“fixedSimilarLabel”,然后考虑新样式。

    $('.toolbar').scroll(function (e) {
//console.info(e.currentTarget.scrollTop);
    if (e.currentTarget.scrollTop >= 130) {
        $('.results-label').addClass('fixedSimilarLabel');
    }
    else {      
        $('.results-label').removeClass('fixedSimilarLabel');
    }
});

http://codepen.io/franklynroth/pen/pjEzeK


1
投票

CSS:

header.sticky {
  font-size: 24px;
  line-height: 48px;
  height: 48px;
  background: #efc47D;
  text-align: left;
  padding-left: 20px;
}

JS:

$(window).scroll(function() {
 if ($(this).scrollTop() > 100){  
    $('header').addClass("sticky");
  }
  else{
    $('header').removeClass("sticky");
  }
});

1
投票

我建议使用sticky js,这是我见过的最好的选择。没什么可做的,只是在你身上广告这个js

 https://raw.githubusercontent.com/garand/sticky/master/jquery.sticky.js

并使用以下代码:

<script>
  $(document).ready(function(){
    $("#sticker").sticky({topSpacing:0});
  });
</script>

它的 git 仓库:https://github.com/garand/sticky


1
投票

这是一个简单的解决方案,仅无需 jQuery Vanilla JS

在示例中,我们只使用 "header" 类,您可以将其更改为您想要的任何其他内容。基本上,它克隆了现有的标头,并将其显示在下面作为固定标头。

该解决方案速度很快,因为动画是通过 CSS 过渡完成的,没有额外的 JS 动画开销。

您可以调整动画样式以拥有自己的过渡。动画 “slidein” 用于在向下滚动时显示固定标题,而 “slideout” 当您希望它在向上滚动到顶部时消失。

(function() {

  //CONFIGURATION
  var headerClassName = 'header'; //Class of your header element
  var stickyAfter = 150; //Show fixed header after this Y offset in px
  
  var header = document.getElementsByClassName(headerClassName)[0];
  var clone = header.cloneNode(true); 
  clone.classList.add('clone'); 
  header.parentElement.appendChild(clone);
  
  var initializeHeader = function() {
    document
    .getElementsByClassName(headerClassName + ' clone')[0]
    .classList.add('initialized');
    return true;
  }
  
  window.onscroll = function() {
    var cl = document.body.classList;
    window.pageYOffset > stickyAfter ? 
      initializeHeader() && cl.add('sticky') : 
      cl.remove('sticky');
  } 

})();
/* GENERAL STYLES */
body {
  min-height: 2000px;
}
.header {
  background: green;
  padding: 7px 20px;
  color: #fff;
  position: relative;
  min-width: 100%;
}

/* STICKY HEADER STYLES */
@keyframes slidein {
  from {
    position: fixed;
    top: -50px;
    opacity: 0;
  }
  to {
    position: fixed;
    top: 0;
    opacity: 1;
  }
}
@keyframes slideout {
  from {
    position: fixed;
    top: 0;
    opacity: 1;
  }
  to {
    position: fixed;
    top: -50px;
    opacity: 0;
  }
}
.header.clone.initialized {
  -webkit-animation: slideout .3s forwards; /* for less modern browsers */
   animation: slideout .3s forwards;
}
body.sticky .header.clone {
  -webkit-animation: slidein .3s forwards; /* for less modern browsers */
   animation: slidein .3s forwards;
}
<div class="header">
  <p>This is demo header</p>
</div>

<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc mollis augue vel massa dictum gravida. Ut vitae elit ligula. In vitae sagittis lacus. Curabitur vel magna eget mauris vestibulum vestibulum id eget dui. Morbi tempus laoreet gravida. Curabitur vel volutpat lacus. Morbi dictum iaculis nibh. Praesent cursus tempor placerat. Sed posuere dui et diam elementum luctus. Nulla aliquet vestibulum justo.</p>

<p>Integer cursus tellus nec sodales lobortis. Donec dictum pharetra ligula, at lobortis lorem pellentesque non. Nullam volutpat nisi id laoreet condimentum. Morbi vel erat vitae elit sodales iaculis ac ut libero. Cras eget neque at libero feugiat interdum. Praesent eget erat mauris. Maecenas convallis aliquet risus non tempus.</p>

<p>Sed convallis elit a dignissim vestibulum. Quisque pharetra, leo eu eleifend pretium, dolor enim viverra elit, quis aliquet dui lacus sit amet dolor. Quisque sit amet sapien tellus. Nam tristique placerat dui, placerat fringilla magna varius nec. Ut id arcu metus. Aenean eu mollis massa. Vestibulum cursus egestas turpis, a tempor metus mattis eu. Donec fringilla quam non fermentum fringilla.</p>

<p>Nam et lorem leo. Donec libero tortor, laoreet quis maximus at, faucibus fermentum ligula. Curabitur facilisis quam in posuere suscipit. Ut sagittis mauris ullamcorper, feugiat sem sed, egestas lorem. Curabitur ut urna laoreet, commodo dolor id, blandit arcu. Aliquam vitae odio magna. Curabitur eu mi dolor. Praesent tellus lectus, mattis eu nunc ac, sagittis tincidunt nulla.</p>

<p>Morbi augue erat, consectetur non pulvinar et, auctor id mi. Vestibulum a ornare diam, nec dignissim neque. Aliquam sodales orci vitae lorem rhoncus, cursus fermentum nisl hendrerit. Aliquam erat volutpat. Mauris fermentum cursus arcu, in imperdiet lacus ultrices ut. Vivamus ligula nulla, mollis a consequat id, varius sed odio. Proin sed fringilla nunc, at dignissim ipsum. Etiam dictum tortor turpis, ac ornare purus semper non. Interdum et malesuada fames ac ante ipsum primis in faucibus. Donec a urna vitae metus vestibulum tincidunt sed gravida metus. Vivamus auctor sed leo eget lacinia. Nulla quis bibendum erat. Nunc dapibus lobortis odio, vel porttitor dui elementum at. Ut neque libero, rutrum vel cursus id, rhoncus vitae felis.</p>


0
投票

使用 jquery 的类似解决方案是:

$(window).scroll(function () {
  $('.header').css('position','fixed');
});

这会在滚动时立即将标题变成固定位置元素


0
投票

添加去抖动,以提高效率http://davidwalsh.name/javascript-debounce-function


0
投票

这在 Firefox 中对我不起作用。

我们根据代码是否将溢出置于 html 级别添加了一个条件。请参阅 动画滚动顶部在 Firefox 中不起作用

  var $header = $("#header #menu-wrap-left"),
  $clone = $header.before($header.clone().addClass("clone"));

  $(window).on("scroll", function() {
    var fromTop = Array(); 
    fromTop["body"] = $("body").scrollTop();
    fromTop["html"] = $("body,html").scrollTop();

if (fromTop["body"]) 
    $('body').toggleClass("down", (fromTop["body"] > 650));

if (fromTop["html"]) 
    $('body,html').toggleClass("down", (fromTop["html"] > 650));

  });

0
投票

使用 jquery 窗口底部滚动到顶部滚动。

 <script> 

 var lastScroll = 0;

 $(document).ready(function($) {

 $(window).scroll(function(){

 setTimeout(function() { 
    var scroll = $(window).scrollTop();
    if (scroll > lastScroll) {

        $("header").removeClass("menu-sticky");

    } 
    if (scroll == 0) {
    $("header").removeClass("menu-sticky");

    }
    else if (scroll < lastScroll - 5) {


        $("header").addClass("menu-sticky");

    }
    lastScroll = scroll;
    },0);
    });
   });
 </script>

0
投票

在现代 javascript 中,使用观察者来实现相同的效果会更好。

CSS

sticky{
  position: fixed;
  top: 0;
}

JS

const header = document.querySelector(".js-header");

function markSticky() {
  categoriesNav.classList.add('sticky')
}

function markUnsticky() {
  categoriesNav.classList.remove('sticky')
}

const observer = new IntersectionObserver(function (entries) {
  entries.forEach(function (entry) {
    if (entry.isIntersecting) {
      markUnsticky()
    } else {
      markSticky()
    }
  })
})

0
投票

这是我的工作代码示例。 它还消除了粘性标题的抖动!!

<script>
    window.onscroll = function() {
        showDesktopMenu()
    };

    function showDesktopMenu() {
        let header = document.querySelector('#header'); //main header div
        let navbar = document.querySelector('.desktop-navbar'); // child div of main header div
        let body = document.querySelector('body'); // document body
        if (window.pageYOffset > header.getBoundingClientRect().height) {
            navbar.classList.add('sticky-custom');
            body.style['padding-top'] = navbar.getBoundingClientRect().height + "px";
        } else {
            body.style['padding-top'] = "0px";
            navbar.classList.remove('sticky-custom');
        }
    }
</script>
<style>
    .sticky-custom {
        position: fixed;
        z-index: 9999;
        width: 100%;
        top: 0;
    }
</style>
© www.soinside.com 2019 - 2024. All rights reserved.