How to fix a header on scroll

后端 未结 12 506
佛祖请我去吃肉
佛祖请我去吃肉 2020-11-27 11:26

I am creating a header that once scrolled to a certain amount of pixels it fixes and stays in place.

Can I do this using just css and html or do i need jquery too?

相关标签:
12条回答
  • 2020-11-27 12:07

    The chosen solution did not fit well in my page. So this is a more advanced version that works with bootstrap.

    The 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
            });
        }
    });
    

    The 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;
    }
    

    And the 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>
    
    0 讨论(0)
  • 2020-11-27 12:09

    I know Coop has already answered this question, but here is a version which also tracks where in the document the div is, rather than relying on a static value:

    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;
    }
    
    0 讨论(0)
  • 2020-11-27 12:11

    You need some JS to do scroll events. The best way to do this is to set a new CSS class for the fixed position that will get assigned to the relevant div when scrolling goes past a certain point.

    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');
    });
    

    Example fiddle: http://jsfiddle.net/gxRC9/501/


    EDIT: Extended example

    If the trigger point is unknown but should be whenever the sticky element reaches the top of the screen, offset().top can be used.

    var stickyOffset = $('.sticky').offset().top;
    
    $(window).scroll(function(){
      var sticky = $('.sticky'),
          scroll = $(window).scrollTop();
    
      if (scroll >= stickyOffset) sticky.addClass('fixed');
      else sticky.removeClass('fixed');
    });
    

    Extended example fiddle: http://jsfiddle.net/gxRC9/502/

    0 讨论(0)
  • 2020-11-27 12:11

    Coop's answer is excellent.
    However it depends on jQuery, here is a version that has no dependencies:

    HTML

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

    CSS

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

    JS
    (This uses eyelidlessness's answer for finding offsets in 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');
        }
      };
    };
    

    Example

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

    0 讨论(0)
  • 2020-11-27 12:16

    Just building on Rich's answer, which uses offset.

    I modified this as follows:

    • There was no need for the var $sticky in Rich's example, it wasn't doing anything
    • I've moved the offset check into a separate function, and called it on document ready as well as on scroll so if the page refreshes with the scroll half-way down the page, it resizes straight-away without having to wait for a scroll trigger

      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');
              } 
          }
      
      });
      
    0 讨论(0)
  • 2020-11-27 12:16

    Coops answer is a good, simple solution, however, once you apply the fixed class the page becomes that much shorter and content will "jump" up, and if page is of a length where the scroll distance is less than the height of the header element, it will appear to jump and not let you see the bottom of the page.

    The answer I found was to add a spacer div above the element that will become fixed (nav element in my case), and set it to the same height as the nav element, and set it to display none.

    When adding the .fixed class to the nav, show the .nav-spacer div, and when removing it, hide it. Since the height of the page changes instantly I have set the duration to 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);
        }
    });
    
    0 讨论(0)
提交回复
热议问题