Comment réparer un en-tête de défilement

je crée un en-tête qui une fois défilé à un certain nombre de pixels, il fixe et reste en place.

puis-je le faire en utilisant seulement css et html ou Ai-je besoin de jquery aussi?

j'ai créé une démo pour que vous puissiez comprendre. Toute aide serait super!

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;
}
33
demandé sur Paul Designer 2013-10-03 15:54:34

10 réponses

vous avez besoin de quelques JS pour faire défiler les événements. La meilleure façon de le faire est de définir une nouvelle classe CSS pour la position fixe qui sera assignée à la div pertinente lorsque le défilement passe un 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');
});

exemple de violon: http://jsfiddle.net/gxRC9/501 /


modifier: exemple étendu

si le point de déclenchement est inconnu mais devrait l'être chaque fois que l'élément collant atteint le haut de l'écran, offset().top peut être utilisé.

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

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

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

violon d'exemple étendu: http://jsfiddle.net/gxRC9/502 /

88
répondu Coop 2014-08-08 11:30:40

j'ai modifié la réponse de Coop. Veuillez cocher l'exemple violon Voici mes modifications:

$(window).scroll(function(){
  if ($(window).scrollTop() >= 330) {
    $('.sticky-header').addClass('fixed');
   }
   else {
    $('.sticky-header').removeClass('fixed');
   }
});
11
répondu Mobeen Abdullah 2014-03-08 11:39:03

Je sais que Coop a déjà répondu à cette question, Mais voici une version qui suit également où dans le document le div est, plutôt que de compter sur une valeur statique:

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;
}
8
répondu Rich 2013-10-03 12:14:33

la réponse de Coop est excellente.

Cependant cela dépend de jQuery, voici une version qui n'a pas de dépendances:

HTML

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

CSS

.sticky {
  width: 100%
}

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

JS

(Cela utilise eyelidlessness la réponse de pour trouver des décalages dans 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');
    }
  };
};

exemple

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

6
répondu RubenSandwich 2016-03-31 16:54:40

Juste en appuyant sur Riches " réponse , qui utilise le décalage.

Je l'ai modifié comme suit:

  • il n'y avait pas besoin de la var $sticky dans L'exemple de Rich, il ne faisait rien
  • j'ai placé le contrôle offset dans une fonction séparée, et je l'ai appelé sur le document prêt, ainsi que sur de défilement si la page se rafraîchit avec l' faites défiler la page à mi-chemin, elle se redimensionne tout de suite sans avoir à attendre un scroll trigger

    jQuery(document).ready(function($){
        var offset = $( "#header" ).offset();
        checkOffset();
    
        $(window).scroll(function() {
            checkOffset();
        });
    
        function checkOffset() {
            if ( $('body').scrollTop() > offset.top){
                $('#header').addClass('fixed');
            } else {
                $('#header').removeClass('fixed');
            } 
        }
    
    });
    
4
répondu crdunst 2017-05-23 12:02:26

Coops réponse est une bonne, solution simple, cependant, une fois que vous appliquez la classe fixe la page devient que beaucoup plus court et le contenu sera "saut" vers le haut, et si la page est d'une longueur où la distance de défilement est inférieure à la hauteur de l'élément d'en-tête, il semblera sauter et ne pas vous laisser voir le bas de la page.

la réponse que j'ai trouvée était d'ajouter un div espaceur au-dessus de l'élément qui va devenir fixe (élément nav dans mon cas), et le mettre à la même hauteur que l'élément nav, et le configurer pour afficher aucun.

en ajoutant le .fixes de classe à la valeur liquidative, de montrer le .nav-spacer div, et en l'enlevant, le cacher. Puisque la hauteur de la page change instantanément, j'ai mis la durée à 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);
    }
});
4
répondu Craig Jacobs 2016-09-29 04:12:01
 $(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':'');

    }); 
});

ça marche parfaitement.

1
répondu arjun 2015-08-04 13:07:08

la solution choisie ne correspondait pas bien à ma page. C'est donc une version plus avancée qui fonctionne avec bootstrap.

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

et le 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>
1
répondu Daniel 2015-08-05 09:37:33

ou tout simplement ajouter une étiquette span avec la hauteur de l'en-tête fixe défini comme sa hauteur, puis l'insérer à côté de l'en-tête collant:

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

  $('.fixed-header').after($span_tag);
});
1
répondu user3721605 2015-11-16 11:18:46

avec un peu de chance, ce morceau de solution alternative sera aussi précieux pour quelqu'un d'autre que pour moi.



Situation :

Dans une page HTML5 j'avais un menu qui était un élément nav à l'intérieur d'un en-tête (pas l'en-tête mais un en-tête dans un autre élément).

Je voulais que la navigation reste collée au dessus une fois qu'un utilisateur s'y est incliné, mais avant cela l'en-tête était absolu positionné (pour que je puisse le superposer légèrement).

Les solutions ci-dessus n'ont jamais déclenché un changement parce que .offsetTop n'allait pas changer car il s'agissait d'un élément absolument positionné. En outre, l' .la propriété scrollTop était simplement le haut de l'élément le plus haut... c'est-à-dire 0 et serait toujours 0.

Tous les tests que j'ai effectués en utilisant ces deux (et même avec getBoundingClientRect résultats) ne me dirait pas si le haut de la la barre de navigation s'est déjà déplacée vers le haut de la page visualisable (encore une fois, comme indiqué dans la console, ils sont simplement restés les mêmes nombres pendant que le défilement s'est produit).

Solution

La solution pour moi était d'utiliser

window.visualViewport.pageTop

la valeur de la propriété pageTop reflète la section visible de l'écran, ce qui me permet de suivre où un élément est en référence à les limites de la zone visible.

Cela permettait une fonction simple assignée à l'événement de défilement de la fenêtre pour détecter quand le haut de la barre de navigation entrecoupé avec le haut de la zone visible et appliquer le style pour le faire coller au sommet.

probablement inutile de dire que, chaque fois que je m'occupe de défilement, je m'attends à utiliser cette solution pour répondre programmatiquement au mouvement des éléments qui sont défilés.

Espérons que cela aide quelqu'un d'autre.

0
répondu MER 2017-10-24 19:41:01