Hoe een header op scrollen te bevestigen

Ik maak een koptekst die ooit naar een zekere mate van pixels scrolte, die oppakt en op zijn plaats blijft.

Kan ik dit doen met alleen CSS en HTML of heb ik ook jQuery nodig?

Ik heb een demo gemaakt, zodat je begrijpt. Elke hulp zou geweldig zijn!

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

Antwoord 1, Autoriteit 100%

Heb je wat JS nodig om scroll-evenementen te doen. De beste manier om dit te doen is om een ​​nieuwe CSS-klasse in te stellen voor de vaste positie die wordt toegewezen aan de relevante DIV wanneer het scrollen voorbij op een bepaald punt gaat.

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

Voorbeeld Fiddle: http://jsfiddle.net/GXRC9/501/


EDIT: uitgebreid voorbeeld

Als het triggerpunt onbekend is, maar zou moeten zijn wanneer het plakkerige element de bovenkant van het scherm bereikt, kan offset().topworden gebruikt.

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

Uitgebreide voorbeeldviool: http://jsfiddle.net/gxRC9/502/


Antwoord 2, autoriteit 12%

Ik heb het antwoord van de Coop aangepast. Bekijk het voorbeeld FIDDLE
Dit zijn mijn bewerkingen:

$(window).scroll(function(){
  if ($(window).scrollTop() >= 330) {
    $('.sticky-header').addClass('fixed');
   }
   else {
    $('.sticky-header').removeClass('fixed');
   }
});

Antwoord 3, autoriteit 8%

Het antwoord van Coop is uitstekend.
Het hangt echter af van jQuery, hier is een versie die geen afhankelijkheden heeft:

HTML

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

CSS

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

JS
(Dit gebruikt antwoord van ooglidloosheidvoor het vinden van 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');
    }
  };
};

Voorbeeld

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


Antwoord 4, autoriteit 8%

Ik weet dat Coop deze vraag al heeft beantwoord, maar hier is een versie die ook bijhoudt waar in het document de div is, in plaats van te vertrouwen op een statische waarde:

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

Antwoord 5, autoriteit 7%

Glorieuze, pure HTML/CSS-oplossing

In 2019 kun je met CSS3 dit helemaal zonder Javascript doen. Ik maak vaak sticky headers als volgt:

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>

Antwoord 6, autoriteit 6%

Gewoon voortbouwen op Het antwoord van Rich, dat offset gebruikt.

Ik heb dit als volgt aangepast:

  • De var $stickyin het voorbeeld van Rich was niet nodig, hij deed niets
  • Ik heb de offsetcontrole naar een aparte functie verplaatst en deze aangeroepen
    zowel op document gereed als op scrollen, dus als de pagina wordt vernieuwd met de
    scroll halverwege de pagina, het formaat wordt meteen aangepast zonder te hoeven wachten op een 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');
            } 
        }
    });
    

Antwoord 7, autoriteit 5%

Het antwoord van Coops is een goede, eenvoudige oplossing, maar zodra u de vaste klasse toepast, wordt de pagina veel korter en zal de inhoud “opspringen”, en als de pagina een lengte heeft waarbij de schuifafstand kleiner is dan de hoogte van het header-element, zal het lijken te springen en u de onderkant van de pagina niet laten zien.

Het antwoord dat ik vond was om een spacer div toe te voegen boven het element dat vast wordt (nav-element in mijn geval), en het op dezelfde hoogte in te stellen als het nav-element, en het zo in te stellen dat er geen wordt weergegeven.

>

Wanneer u de klasse .fixed aan de nav toevoegt, moet u de .nav-spacer div tonen en wanneer u deze verwijdert, deze verbergen. Omdat de hoogte van de pagina onmiddellijk verandert, heb ik de duur op 0 gezet.

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

Antwoord 8, autoriteit 2%

Of voeg gewoon een span-tag toe met de hoogte van de vaste kop als hoogte en voeg deze vervolgens in naast de plakkop:

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

Antwoord 9, autoriteit 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':'');
    }); 
});

Het werkt perfect.


Antwoord 10, autoriteit 2%

De gekozen oplossing paste niet goed op mijn pagina. Dit is dus een meer geavanceerde versie die werkt met bootstrap.

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

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

En de 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>

Antwoord 11

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

Antwoord 12

Hopelijk is dit stukje van een alternatieve oplossing net zo waardevol voor iemand anders als voor mij.

Situatie:
Op een HTML5-pagina had ik een menu dat een nav-element was in een koptekst (niet DE koptekst maar een koptekst in een ander element).
Ik wilde dat de navigatie bovenaan bleef staan zodra een gebruiker ernaartoe scrolde, maar daarvoor was de koptekst absoluut gepositioneerd (zodat ik hem iets anders kon laten overlappen).
De bovenstaande oplossingen brachten nooit een verandering teweeg omdat .offsetTop niet zou veranderen omdat dit een absoluut gepositioneerd element was. Bovendien was de eigenschap .scrollTop gewoon de top van het bovenste element… dat wil zeggen 0 en zou altijd 0 zijn.
Alle tests die ik heb uitgevoerd met deze twee (en hetzelfde met getBoundingClientRect-resultaten) zouden me niet vertellen of de bovenkant van de navigatiebalk ooit naar de bovenkant van de zichtbare pagina scrolde (nogmaals, zoals gerapporteerd in de console, bleven ze gewoon dezelfde nummers tijdens het scrollen heeft plaatsgevonden).

Oplossing

De oplossing voor mij was het gebruik van

window.visualViewport.pageTop

De waarde van de eigenschap pageTop geeft het zichtbare gedeelte van het scherm weer, waardoor ik kan volgen waar een element zich bevindt ten opzichte van de grenzen van het zichtbare gebied.
Hierdoor kon een eenvoudige functie toegewezen aan de scroll-gebeurtenis van het venster detecteren wanneer de bovenkant van de navigatiebalk de bovenkant van het zichtbare gebied kruiste en de stijl toepassen om het aan de bovenkant te laten plakken.

Waarschijnlijk onnodig om te zeggen, wanneer ik met scrollen te maken heb, verwacht ik deze oplossing te gebruiken om programmatisch te reageren op beweging van elementen die worden gescrolld.

Ik hoop dat het iemand anders helpt.


Antwoord 13

De eenvoudigste manier is:
HTML:

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

CSS:

header{
    position: sticky;
    top: 0;
}

Antwoord 14

Als je React gebruikt, heb ik onlangs een aangepaste hookgepubliceerd waarmee je dit kunt doen . Je moet een ref opgeven voor het plakkerige element en een ref voor het element waar je het aan de bovenkant wilt laten plakken. Het behandelt ook de scherm “springen” (zoals vermeld in andere reacties) voor jou.

const sticky = useRef<HTMLDivElement>(null)
const container = useRef<HTMLDivElement>(null)
useStickyScroll({
    element: sticky,
    container: container
})

Antwoord 15

Mijn oplossing voor het weergeven van koptekst als de gebruiker het document van onder naar boven scrolt.

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

Other episodes