58

我正在创建一个标题,一旦滚动到一定数量的像素,它就会修复并保持在原位。

我可以只使用 css 和 html 来做到这一点,还是我也需要 jquery?

我创建了一个演示,以便您理解。任何帮助都会很棒!

http://jsfiddle.net/gxRC9/4/

body{
     margin:0px;
     padding:0px;
}
 .clear{
     clear:both;
}
 .container{
     height:2000px;
}
 .cover-photo-container{
     width:700px;
     height: 348px;
     margin-bottom: 20px;
     background-color:red;
}
 .small-box{
     width:163px;
     height:100px;
     border:1px solid blue;
     float:left;
}
 .sticky-header{
     width:700px;
     height:50px;
     background:orange;
     postion:fixed;
}


4

16 回答 16

136

您需要一些 JS 来执行滚动事件。最好的方法是为固定位置设置一个新的 CSS 类,当滚动超过某个点时,该类将分配给相关的 div。

HTML

<div class="sticky"></div>

CSS

.fixed {
    position: fixed;
    top:0; left:0;
    width: 100%; }

jQuery

$(window).scroll(function(){
  var sticky = $('.sticky'),
      scroll = $(window).scrollTop();

  if (scroll >= 100) sticky.addClass('fixed');
  else sticky.removeClass('fixed');
});

小提琴示例:http: //jsfiddle.net/gxRC9/501/


编辑:扩展示例

如果触发点未知但应该是每当粘性元素到达屏幕顶部时,offset().top都可以使用。

var stickyOffset = $('.sticky').offset().top;

$(window).scroll(function(){
  var sticky = $('.sticky'),
      scroll = $(window).scrollTop();

  if (scroll >= stickyOffset) sticky.addClass('fixed');
  else sticky.removeClass('fixed');
});

扩展示例小提琴:http: //jsfiddle.net/gxRC9/502/

于 2013-10-03T12:00:56.590 回答
15

我已经修改了合作社的答案。请检查示例FIDDLE 这是我的编辑:

$(window).scroll(function(){
  if ($(window).scrollTop() >= 330) {
    $('.sticky-header').addClass('fixed');
   }
   else {
    $('.sticky-header').removeClass('fixed');
   }
});
于 2014-03-08T11:12:59.230 回答
12

库普的回答非常好。
但是它依赖于 jQuery,这是一个没有依赖关系的版本:

HTML

<div id="sticky" class="sticky"></div>

CSS

.sticky {
  width: 100%
}

.fixed {
  position: fixed;
  top:0;
}

JS
(这使用eyelidlessness 的答案来查找 Vanilla JS 中的偏移量。)

function findOffset(element) {
  var top = 0, left = 0;

  do {
    top += element.offsetTop  || 0;
    left += element.offsetLeft || 0;
    element = element.offsetParent;
  } while(element);

  return {
    top: top,
    left: left
  };
}

window.onload = function () {
  var stickyHeader = document.getElementById('sticky');
  var headerOffset = findOffset(stickyHeader);

  window.onscroll = function() {
    // body.scrollTop is deprecated and no longer available on Firefox
    var bodyScrollTop = document.documentElement.scrollTop || document.body.scrollTop;

    if (bodyScrollTop > headerOffset.top) {
      stickyHeader.classList.add('fixed');
    } else {
      stickyHeader.classList.remove('fixed');
    }
  };
};

例子

https://jsbin.com/walabebita/edit?html,css,js,输出

于 2016-03-31T16:54:40.073 回答
10

我知道 Coop 已经回答了这个问题,但这里有一个版本,它还跟踪 div 在文档中的位置,而不是依赖于静态值:

http://jsfiddle.net/gxRC9/16/

Javascript

var offset = $( ".sticky-header" ).offset();
var sticky = document.getElementById("sticky-header")

$(window).scroll(function() {

    if ( $('body').scrollTop() > offset.top){
        $('.sticky-header').addClass('fixed');
    } else {
         $('.sticky-header').removeClass('fixed');
    } 

});

CSS

.fixed{
     position: fixed;
    top: 0px;
}
于 2013-10-03T12:14:33.220 回答
9

光荣的纯 HTML/CSS 解决方案

在 2019 年,使用 CSS3,您完全可以在没有 Javascript 的情况下做到这一点。我经常制作这样的粘性标题:

body {
  overflow-y: auto;
  margin: 0;
}

header {
  position: sticky; /* Allocates space for the element, but moves it with you when you scroll */
  top: 0; /* specifies the start position for the sticky behavior - 0 is pretty common */
  width: 100%;
  padding: 5px 0 5px 15px;
  color: white;
  background-color: #337AB7;
  margin: 0;
}

h1 {
  margin: 0;
}

div.big {
  width: 100%;
  min-height: 150vh;
  background-color: #1ABB9C;
  padding: 10px;
}
<body>
<header><h1>Testquest</h1></header>
<div class="big">Just something big enough to scroll on</div>
</body>

于 2019-03-19T15:53:29.753 回答
8

只是建立在Rich's answer 的基础上,它使用了偏移量。

我将其修改如下:

  • Rich 的示例中不需要 var $sticky,它没有做任何事情
  • 我已经将偏移检查移到一个单独的函数中,并在文档准备好和滚动时调用它,所以如果页面在页面中途滚动刷新,它会立即调整大小而无需等待滚动扳机

    jQuery(document).ready(function($){
        var offset = $( "#header" ).offset();
        checkOffset();
    
        $(window).scroll(function() {
            checkOffset();
        });
    
        function checkOffset() {
            if ( $(document).scrollTop() > offset.top){
                $('#header').addClass('fixed');
            } else {
                $('#header').removeClass('fixed');
            } 
        }
    
    });
    
于 2016-03-01T12:20:28.293 回答
6

Coops 的回答是一个很好、简单的解决方案,但是,一旦应用了固定类,页面就会变得更短,并且内容会“跳”起来,并且如果页面的长度是滚动距离小于标题的高度元素,它会出现跳跃而不是让你看到页面底部。

我找到的答案是在将变为固定的元素(在我的情况下为导航元素)上方添加一个分隔符 div,并将其设置为与导航元素相同的高度,并将其设置为不显示。

将 .fixed 类添加到 nav 时,显示 .nav-spacer div,删除它时,将其隐藏。由于页面的高度会立即改变,因此我将持续时间设置为 0。

HTML

<header>the element above the element that will become fixed</header>
<div class="nav-spacer"></div>
<nav></nav>

CSS

nav {
    position: relative;    
    height: 100px;
}
.nav-spacer{
    position: relative;
    height: 100px;
    display: none;
}
.fixed {
    position: fixed;
    top:0;
    left:0;
    width: 100%;
    /* I like to add a shadow on to the fixed element */
    -webkit-box-shadow: 0px 5px 10px 1px rgba(0,0,0,0.25);
    -moz-box-shadow: 0px 5px 10px 1px rgba(0,0,0,0.25);
    box-shadow: 0px 5px 10px 1px rgba(0,0,0,0.25);
}

JavaScript

var stickyOffset = $('nav').offset().top;

$(window).scroll(function(){
    if ($(window).scrollTop() >= stickyOffset){
        $('nav').addClass('fixed');
        //this makes the page length equal to what it was before fixing nav
        $('.nav-spacer').show(0); 
    }
    else {
        $('nav').removeClass('fixed');
        $('.nav-spacer').hide(0);
    }
});
于 2016-09-29T04:12:01.457 回答
4

可以通过仅使用 CSS 来完成

.sticky-header {
  position: sticky;
  top: 0;
  background: orange;
}

body {
  margin: 0px;
  padding: 0px;
}

.clear {
  clear: both;
}

.container {
  height: 2000px;
}

.cover-photo-container {
  width: 700px;
  height: 100px;
  margin-bottom: 20px;
  background-color: red;
}

.small-box {
  width: 163px;
  height: 100px;
  border: 1px solid blue;
  float: left;
}

.sticky-header {
  position: sticky;
  top: 0;
  background: orange;
}
<div class="container">
  <div class="cover-photo-container">
    Please scroll
  </div>
  <div class="small-box"></div>
  <div class="small-box"></div>
  <div class="small-box"></div>
  <div class="small-box"></div>
  <div class="clear"></div>
  <div class="sticky-header">
    This needs to be fixed when hits top of screen
  </div>
</div>

于 2021-10-30T08:40:58.290 回答
3

或者只是简单地添加一个span标签,将固定标题的高度设置为其高度,然后将其插入到粘性标题旁边:

$(function() {
  var $span_height = $('.fixed-header').height;
  var $span_tag = '<span style="display:block; height:' + $span_height + 'px"></span>';

  $('.fixed-header').after($span_tag);
});
于 2015-11-16T10:56:55.207 回答
2
 $(document).ready(function(){

    var div=$('#header');
    var start=$(div).offset().top;

    $.event.add(window,'scroll',function(){
        var p=$(window).scrollTop();
        $(div).css('position',(p>start)?'fixed':'static');
        $(div).css('top',(p>start)?'0px':'');

    }); 
});

它完美地工作。

于 2015-08-04T13:07:08.847 回答
2

选择的解决方案不适合我的页面。所以这是一个更高级的版本,可以与引导程序一起使用。

javascript

var stickyOffset = $('.sticky-header').offset().top;

$(window).scroll(function () {
    var sticky = $('.sticky-header'),
        scroll = $(window).scrollTop(),
        header = $('.fixed-header-background');
    sticky.each(function() {
        var left = $(this).offset().left;
        $(this).data('left', left);//I store the left offset
    });

    if (scroll >= stickyOffset) {
        sticky.addClass('fixed');
        header.css('display', 'block');
        sticky.each(function() {
            $(this).css('left', $(this).data('left'));//I set the left offset
        });
    } else {
        sticky.removeClass('fixed');
        header.css('display', 'none');
        sticky.each(function () {
            $(this).css('left', '');//I remove the left offset
        });
    }
});

CSS

.fixed-header-background {
    display: none;
     position: fixed;
    top: 50px;
    width: 100%;
    height: 30px;
    background-color: #fff;
    z-index: 5;
    border-bottom-style: solid;
    border-bottom-color: #dedede;
    border-bottom-width: 2px;
}

.fixed{
     position: fixed;
    top: 52px;
    z-index: 6;
}

和 HTML

    <div class="fixed-header-background"></div>
<table class="table table-hover table-condensed">
        <thead>
            <tr>
                <th></th>
                <th><span class="sticky-header">My header 1</span></th>
                <th><span class="sticky-header">My header 2</span></th>
            </tr>
        </thead>
        <tbody>
[....]

        </tbody>
    </table>
于 2015-08-05T09:37:33.693 回答
1
custom scroll Header Fixed in shopify:

$(window).scroll(function(){
  var sticky = $('.site-header'),
      scroll = $(window).scrollTop();

  if (scroll >= 100) sticky.addClass('fixed');
  else sticky.removeClass('fixed');
})


css:


header.site-header.border-bottom.logo--left.fixed {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    z-index: 9;
}
于 2021-01-15T03:39:39.477 回答
0

希望这一替代解决方案对其他人和我一样有价值。

情况
在 HTML5 页面中,我有一个菜单,它是标题内的导航元素(不是标题,而是另一个元素中的标题)。
一旦用户滚动到它,我希望导航保持在顶部,但在此之前,标题是绝对定位的(所以我可以让它稍微覆盖其他东西)。
上面的解决方案从未触发更改,因为 .offsetTop 不会更改,因为这是一个绝对定位的元素。此外, .scrollTop 属性只是最顶部元素的顶部......也就是说 0 并且始终为 0。
我使用这两个执行的任何测试(与 getBoundingClientRect 结果相同)都不会告诉我导航栏的顶部是否曾经滚动到可查看页面的顶部(再次,如控制台中报告的那样,它们在滚动时只是保持相同的数字发生了)。

解决
方案我的解决方案是利用

window.visualViewport.pageTop

pageTop 属性的值反映了屏幕的可视部分,因此允许我跟踪元素相对于可视区域边界的位置。
这允许分配给窗口滚动事件的简单函数来检测导航栏顶部何时与可视区域顶部相交并应用样式以使其粘在顶部。

可能没必要说,每当我处理滚动时,我都希望使用此解决方案以编程方式响应正在滚动的元素的移动。
希望它可以帮助别人。

于 2017-10-24T19:41:01.840 回答
0

最简单的方法是:HTML:

<header>
        <h1>Website</h1>
</header>

CSS:

header{
    position: sticky;
    top: 0;
}
于 2020-09-02T14:55:42.643 回答
0

如果你使用 React,我最近发布了一个自定义钩子,可以让你做到这一点。您需要为粘性元素提供 ref 以及您希望它粘贴到顶部的元素的 ref。它也为您处理屏幕“跳转”(如其他回复中所述)。

const sticky = useRef<HTMLDivElement>(null)
const container = useRef<HTMLDivElement>(null)

useStickyScroll({
    element: sticky,
    container: container
})
于 2021-01-11T18:42:20.787 回答
0

如果用户从下到上滚动文档,我的显示标题的解决方案。

JS:

const isMobile = window.innerWidth < 768
const $header = $('#header')
let lastScrollTop = 0
if ( isMobile ) {
    $(window).scroll(function () {
        const scrollTop = window.pageYOffset || document.documentElement.scrollTop

        if ( scrollTop < lastScrollTop ) {
            $header.removeClass('header_top')
        } else {
            $header.addClass( 'header_top' )    
        }

        lastScrollTop = scrollTop <= 0 ? 0 : scrollTop
    })
}

CSS

.header {
    position: fixed;
    top: 0;
    z-index: 70;
    width: 100vw;
    transition: top .5s;
    height: 62px;
}
.header_top {
    top: -62px;
}
于 2021-08-11T09:16:31.933 回答