432 votes

Comment faire en sorte qu'un div reste en haut de l'écran après avoir été défilé ?

Je voudrais créer un div, situé sous un bloc de contenu, mais qui, une fois que la page a été suffisamment déroulée pour entrer en contact avec sa limite supérieure, devient fixe en place et défile avec la page.

6 votes

En juin 2014, le Plugin jQuery Sticky-kit est l'une des options les plus simples, offrant une barrière d'entrée extrêmement basse et de nombreuses fonctionnalités. C'est un bon point de départ si vous cherchez un moyen facile de démarrer rapidement.

2 votes

63 votes

Ajout de CSS position: sticky; top:0; fonctionne dans la plupart des navigateurs en janvier 2017.

364voto

CMS Points 315406

Vous pourriez utiliser simplement du css, en positionnant votre élément comme Correction de :

.fixedElement {
    background-color: #c0c0c0;
    position:fixed;
    top:0;
    width:100%;
    z-index:100;
}

Edit : L'élément doit avoir une position absolue. Une fois que le décalage de défilement a atteint l'élément, il doit devenir fixe et la position supérieure doit être mise à zéro.

Vous pouvez détecter le décalage de défilement supérieur du document avec la fonction scrollTop fonction :

$(window).scroll(function(e){ 
  var $el = $('.fixedElement'); 
  var isPositionFixed = ($el.css('position') == 'fixed');
  if ($(this).scrollTop() > 200 && !isPositionFixed){ 
    $el.css({'position': 'fixed', 'top': '0px'}); 
  }
  if ($(this).scrollTop() < 200 && isPositionFixed){
    $el.css({'position': 'static', 'top': '0px'}); 
  } 
});

Lorsque le décalage de défilement atteint 200, l'élément bâton en haut de la fenêtre du navigateur, car il est placé comme fixe.

9 votes

Qui n'atteint pas ce que je cherche. J'aimerais que l'élément commence à 200px en dessous du haut de la page (pour laisser de la place à d'autres contenus) et qu'une fois que l'utilisateur a fait défiler la page, il se fixe en haut.

3 votes

Votre modification répond en effet aux besoins de la question maintenant mais vous avez toujours un problème lorsque la page défile à nouveau vers le haut. vous pourriez après avoir atteint l'élément scrollTop le stocker quelque part, et lorsque la page atteint à nouveau cette position (lors du défilement vers le haut) changer la css pour revenir à la valeur par défaut... probablement mieux de faire cela avec un .toggleClass alors...

9 votes

C'est à peu près ce que j'ai fait, mais j'ai dû supprimer le positionnement fixe lorsque la fenêtre est déroulée vers le haut. if ($(this).scrollTop() < 200 && $el.css('position') == 'fixed') { $('.fixedElement').css({'position': 'static', 'top': '0px'}); }

254voto

Josh Lee Points 53741

Vous avez déjà vu cet exemple sur le site de Google Code page de sortie et (tout récemment) sur la page d'édition de Stack Overflow.

La réponse du CMS ne rétablit pas le positionnement lorsque vous faites défiler la page vers le haut. Voici le code volé sans vergogne sur Stack Overflow :

function moveScroller() {
    var $anchor = $("#scroller-anchor");
    var $scroller = $('#scroller');

    var move = function() {
        var st = $(window).scrollTop();
        var ot = $anchor.offset().top;
        if(st > ot) {
            $scroller.css({
                position: "fixed",
                top: "0px"
            });
        } else {
            $scroller.css({
                position: "relative",
                top: ""
            });
        }
    };
    $(window).scroll(move);
    move();
}

<div id="sidebar" style="width:270px;"> 
  <div id="scroller-anchor"></div> 
  <div id="scroller" style="margin-top:10px; width:270px"> 
    Scroller Scroller Scroller
  </div>
</div>

<script type="text/javascript"> 
  $(function() {
    moveScroller();
  });
</script> 

Et un simple Démonstration en direct .

Une alternative naissante, script-free est position: sticky qui est pris en charge par Chrome, Firefox et Safari. Voir le article sur HTML5Rocks y Démonstration y Documents de Mozilla .

3 votes

Pour une raison quelconque, le {scroll:false} me posait problème (jQuery 1.6.2). Il semble que cela fonctionne sans. Fourche de la démo liée. Savez-vous si cela sert à quelque chose ?

0 votes

J'ai beaucoup de mal avec ce système, je n'arrive pas à le reproduire, j'ai même essayé de reproduire la démo en direct et ça ne marche pas. Quelqu'un peut-il me donner un lien vers un tutoriel qui donne des instructions étape par étape ?

2 votes

Cela semble fonctionner parfaitement, lorsque j'utilise la même version de jQuery que la démo (1.3.2). A un moment donné offset doit avoir cessé d'accepter un objet en entrée api.jquery.com/offset . @Eddie Votre modification devrait être sûre avec le jQuery actuel.

35voto

Jim W Points 1089

Et voici comment sans jquery (MISE À JOUR : voir d'autres réponses où vous pouvez maintenant faire cela avec CSS seulement)

var startProductBarPos=-1;
window.onscroll=function(){
  var bar = document.getElementById('nav');
  if(startProductBarPos<0)startProductBarPos=findPosY(bar);

  if(pageYOffset>startProductBarPos){
    bar.style.position='fixed';
    bar.style.top=0;
  }else{
    bar.style.position='relative';
  }

};

function findPosY(obj) {
  var curtop = 0;
  if (typeof (obj.offsetParent) != 'undefined' && obj.offsetParent) {
    while (obj.offsetParent) {
      curtop += obj.offsetTop;
      obj = obj.offsetParent;
    }
    curtop += obj.offsetTop;
  }
  else if (obj.y)
    curtop += obj.y;
  return curtop;
}

* {margin:0;padding:0;}
.nav {
  border: 1px red dashed;
  background: #00ffff;
  text-align:center;
  padding: 21px 0;

  margin: 0 auto;
  z-index:10; 
  width:100%;
  left:0;
  right:0;
}

.header {
  text-align:center;
  padding: 65px 0;
  border: 1px red dashed;
}

.content {
  padding: 500px 0;
  text-align:center;
  border: 1px red dashed;
}
.footer {
  padding: 100px 0;
  text-align:center;
  background: #777;
  border: 1px red dashed;
}

<header class="header">This is a Header</header>
<div id="nav" class="nav">Main Navigation</div>
<div class="content">Hello World!</div>
<footer class="footer">This is a Footer</footer>

4 votes

Merci ! Il devient difficile de trouver des solutions JS natives ces jours-ci. Cela a parfaitement fonctionné.

0 votes

Merci beaucoup, cela a parfaitement fonctionné car jquery était en conflit avec un code d'entreprise hérité que mon projet possède.

0 votes

Mais je rencontre un problème : si je fais défiler la page jusqu'en bas, elle remonte automatiquement en haut de la page.

33voto

Donny V. Points 4229

J'ai eu le même problème que vous et j'ai fini par créer un plugin jQuery pour m'en occuper. Il résout en fait tous les problèmes que les gens ont énumérés ici, en plus d'ajouter quelques fonctions facultatives.

Options

stickyPanelSettings = {
    // Use this to set the top margin of the detached panel.
    topPadding: 0,

    // This class is applied when the panel detaches.
    afterDetachCSSClass: "",

    // When set to true the space where the panel was is kept open.
    savePanelSpace: false,

    // Event fires when panel is detached
    // function(detachedPanel, panelSpacer){....}
    onDetached: null,

    // Event fires when panel is reattached
    // function(detachedPanel){....}
    onReAttached: null,

    // Set this using any valid jquery selector to 
    // set the parent of the sticky panel.
    // If set to null then the window object will be used.
    parentSelector: null
};

https://github.com/donnyv/sticky-panel

démo : http://htmlpreview.github.io/?https://github.com/donnyv/sticky-panel/blob/master/jquery.stickyPanel/Main.htm

1 votes

Hé ! Merci ! C'est une excellente solution, et merci de l'avoir partagée, cela m'a certainement fait gagner beaucoup de temps. Cela devrait être la solution acceptée pour cette question, car d'après ce que j'ai lu, c'est la solution la plus complète. En fait, les autres solutions ne résolvent pas le problème de la position X originale d'un bloc après l'application du style position : fixed. La vôtre résout ce problème. Vraiment, merci beaucoup !

0 votes

Hey Donny, j'aime aussi votre plugin (v1.4.1)... mais j'ai rencontré un problème, les éléments de bloc perdaient leur largeur si aucune n'était spécifiée. Cela a donc été modifié lors du détachement... seulement en fixant la largeur pour qu'elle reste la même. code // Détacher le panneau node.css({"margin" : 0, "left" : nodeLeft, "top" : newNodeTop, "position" : "fixed", "width" : node.width() }) ; code

0 votes

J'ai cherché et essayé de nombreuses solutions, et celle-ci a fonctionné "tout de suite". Un travail étonnant ! Merci !

11voto

JohnB Points 68

Voici comment je l'ai fait avec Jquery. Tout cela a été bricolé à partir de diverses réponses sur stack overflow. Cette solution met en cache les sélecteurs pour une performance plus rapide et résout également le problème de "saut" lorsque la div collante devient collante.

Découvrez-le sur jsfiddle : http://jsfiddle.net/HQS8s/

CSS :

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

JS :

$(document).ready(function() {
    // Cache selectors for faster performance.
    var $window = $(window),
        $mainMenuBar = $('#mainMenuBar'),
        $mainMenuBarAnchor = $('#mainMenuBarAnchor');

    // Run this on scroll events.
    $window.scroll(function() {
        var window_top = $window.scrollTop();
        var div_top = $mainMenuBarAnchor.offset().top;
        if (window_top > div_top) {
            // Make the div sticky.
            $mainMenuBar.addClass('stick');
            $mainMenuBarAnchor.height($mainMenuBar.height());
        }
        else {
            // Unstick the div.
            $mainMenuBar.removeClass('stick');
            $mainMenuBarAnchor.height(0);
        }
    });
});

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X