web-dev-qa-db-fra.com

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

Je crée un en-tête qui, une fois sélectionné, fixe et reste en place. 

Puis-je faire cela en utilisant seulement css et html ou ai-je aussi besoin de jquery? 

J'ai créé une démo pour que vous puissiez comprendre. Toute aide est la bienvenue!

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;
}
38
Paul Designer

Vous avez besoin de JS pour faire des événements de défilement. 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 appropriée lorsque le défilement dé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/


EDIT: exemple étendu

Si le point de déclenchement est inconnu mais doit l'être chaque fois que l'élément collant atteint le haut de l'écran, vous pouvez utiliser 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');
});

Exemple étendu de violon: http://jsfiddle.net/gxRC9/502/

101
Coop

J'ai modifié la réponse de la coopérative. Veuillez vérifier l'exemple FIDDLE Voici mes modifications:

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

Je sais que Coop a déjà répondu à cette question, mais voici une version qui permet également de savoir où se trouve la div dans le document, 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;
}
9
Rich

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
(Ceci utilise eyelidlessness answer pour trouver des compensations 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,output

7
RubenSandwich

Il suffit de construire sur la réponse de Rich , qui utilise offset.

J'ai modifié ceci comme suit:

  • Il n'y avait aucun besoin de var $sticky dans l'exemple de Rich, cela ne faisait rien
  • J'ai déplacé le contrôle de décalage dans une fonction distincte et je l'ai appelé Sur document prêt ainsi que sur défilement. Ainsi, si la page est actualisée avec le Faire défiler à mi-chemin, elle est redimensionnée immédiatement avoir à attendre un déclencheur de défilement

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

La réponse de Coops est une bonne solution simple, cependant, une fois que vous appliquez la classe fixe, la page devient beaucoup plus courte et le contenu "saute" vers le haut. Si la page est d'une longueur où la distance de défilement est inférieure à la hauteur de l'en-tête. élément, 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 séparateur d’espacement au-dessus de l’élément qui deviendrait fixe (l’élément nav dans mon cas), de le définir à la même hauteur que l’élément nav et de ne rien afficher.

Lors de l'ajout de la classe .fixed à la navigation, affichez le fichier .nav-spacer div et masquez-le lors de son retrait. Depuis que la hauteur de la page change instantanément, j'ai réglé 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
Craig Jacobs

Ou simplement, ajoutez simplement une balise span avec la hauteur de l'en-tête fixe définie, puis insérez-la à 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);
});
2
user3721605
 $(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 fonctionne parfaitement.

1
arjun

La solution choisie ne convenait pas à ma page. Donc, ceci est 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
        });
    }
});

Le 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
Daniel

Espérons que cette solution alternative aura autant de valeur pour quelqu'un d'autre qu'elle l'était pour moi .

Situation:
Dans une page HTML5, mon menu était un élément de navigation situé dans un en-tête (pas THE en-tête mais un en-tête dans un autre élément).
Je voulais que la navigation reste en haut une fois qu'un utilisateur l'a fait défiler, mais auparavant, l'en-tête était positionné de manière absolue (pour que je puisse le superposer légèrement).
Les solutions ci-dessus n'ont jamais provoqué de changement car .offsetTop n'allait pas changer car il s'agissait d'un élément de positionnement absolu. De plus, la propriété .scrollTop était tout simplement le sommet du premier élément le plus haut ... c’est-à-dire 0 et serait toujours 0.
Les tests que j'ai effectués en utilisant ces deux résultats (et les mêmes avec les résultats de getBoundingClientRect) ne me disaient pas si le haut de la barre de navigation avait jamais défilé jusqu'en haut de la page visible les nombres pendant le défilement se sont produits). 

Solution
La solution pour moi utilisait 

window.visualViewport.pageTop

La valeur de la propriété pageTop reflète la section visible de l'écran, ce qui me permet donc de savoir où se trouve un élément par rapport aux limites de la zone visible.
Cela a permis à une simple fonction affectée à l'événement de défilement de la fenêtre de détecter le moment où le haut de la barre de navigation se croisait avec le haut de la zone visible et d'appliquer le style pour le coller au haut.

Il est probablement inutile de dire que, chaque fois que je traite de défilement, je compte utiliser cette solution pour répondre par programme aux mouvements d’éléments défilés.
J'espère que ça aide quelqu'un d'autre.

0
MER