Comment puis-je faire coller un div en haut de l'écran une fois qu'il a été fait défiler?

305

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

evanr
la source
5
Depuis juin 2014, le plugin Sticky-kit jQuery est l'une des options les plus simples, offrant une barrière à l'entrée extrêmement faible et de nombreuses fonctionnalités. Un bon point de départ si vous cherchez un moyen facile de décoller rapidement.
user456584
1
Astuces
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
33
L'ajout de CSS position: sticky; top:0;fonctionne dans la plupart des navigateurs en janvier 2017.
Colin 't Hart
9
Putain de merde, cette position: sticky;chose est magique.
tscizzle

Réponses:

260

Vous pouvez utiliser simplement CSS, en positionnant votre élément comme fixe :

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

Modifier: Vous devez avoir l'élément avec la position absolue, une fois que le décalage de défilement a atteint l'élément, il doit être changé en fixe et la position supérieure doit être définie sur zéro.

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

$(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éfilement atteint 200 décalage, l'élément bâton en haut de la fenêtre du navigateur, car est placé comme fixe.

CMS
la source
4
qui n'atteint pas ce que je veux. J'aimerais que l'élément commence à 200 pixels sous le haut de la page (pour laisser de la place à d'autres contenus), puis une fois que l'utilisateur a fait défiler vers le bas, il se fixe en haut.
evanr
3
votre modification répond en effet aux besoins de la question maintenant, mais vous avez toujours un problème lorsque la page revient à nouveau en haut. vous pourriez après avoir atteint l'élément scrollTop le stocker quelque part, et lorsque la page atteindra à nouveau cette position (lors du défilement vers le haut), redéfinissez le css par défaut ... probablement mieux de le faire avec un .toggleClass puis ...
Sander
9
C'est à peu près ce qui se passe avec, mais j'ai dû supprimer le positionnement fixe lorsque la fenêtre est défilée vers le haut. if ($(this).scrollTop() < 200 && $el.css('position') == 'fixed') { $('.fixedElement').css({'position': 'static', 'top': '0px'}); }
Derrick Petzold
1
@DerrickPetzold J'ai mis cela dans la réponse, des trucs assez importants :)
MarioDS
1
le new examplelien que vous avez donné est tellement propre et clair que je ne le vois même pas! -_-
sohaiby
245

Vous avez vu cet exemple sur la page de problème de Google Code et (tout récemment) sur la page de modification de Stack Overflow.

La réponse de CMS ne inverse pas le positionnement lorsque vous faites défiler vers le haut. Voici le code sans vergogne volé de 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 une simple démo en direct .

Une alternative naissante et sans script position: stickyest prise en charge par Chrome, Firefox et Safari. Voir l' article sur HTML5Rocks et démo , et les documents Mozilla .

Josh Lee
la source
3
Pour une raison quelconque, le {scroll: false} me posait des problèmes (jQuery 1.6.2). Semble fonctionner sans elle. Fork de la démo liée. Une idée si cela sert un but?
Eddie
J'ai beaucoup de problèmes avec ça, pour la vie de moi je ne peux pas reproduire, j'ai même essayé de reproduire la démo en direct et ça ne fonctionne pas. quelqu'un peut-il créer un lien vers un didacticiel qui fournit des instructions étape par étape?
Trevor Dupp,
2
Cela semble fonctionner très bien, lorsque j'utilise la même version de jQuery que la démo (1.3.2). À un moment donné, offsetil a dû cesser d'accepter un objet comme entrée api.jquery.com/offset . @Eddie Votre modification devrait être sûre avec jQuery actuel.
Graeme
1
Yat - il une raison quelconque vous ne pouvez remplacer var d = $("#scroller-anchor").offset().top;avec var d = $("#sidebar").offset().top;et de se débarrasser de la div changeurs ancre vide tous ensemble? Voici ma fourchette démontrant de quoi je parle.
Mike Deck
@MikeDeck Je soupçonne que s'il y a des marges ou du rembourrage, vous aimeriez pouvoir contrôler où la roulette est positionnée par rapport au conteneur.
Josh Lee
72

Depuis janvier 2017 et la sortie de Chrome 56, la plupart des navigateurs couramment utilisés prennent en charge la position: stickypropriété en CSS.

#thing_to_stick {
  position: sticky;
  top: 0px;
}

fait l'affaire pour moi dans Firefox et Chrome.

Dans Safari, vous devez toujours utiliser position: -webkit-sticky.

Les polyfills sont disponibles pour Internet Explorer et Edge; https://github.com/wilddeer/stickyfill semble être un bon.

Colin 't Hart
la source
5
Ceci est pris en charge dans la plupart des navigateurs couramment utilisés aujourd'hui. Voir caniuse.com/#feat=css-sticky. Deuxièmement, je préfère de loin une solution qui peut se résumer à 2 lignes de code à une version qui nécessite Javascript personnalisé. Et c'est aussi une solution d'avenir. Utilisez un polyfill si vous êtes préoccupé par la compatibilité du navigateur.
Colin 't Hart du
1
Ne peut pas être plus facile que cela :)
mestarted
1
Je voudrais ajouter à ce commentaire que nous pouvons z-index: 99999 ;, parce que sinon quand il va en haut, l'autre contenu sera rendu en premier. Mais cela devrait être la solution acceptée.
dayanrr91
Il suffit de l'envelopper dans un div avec id = "thing_to_stick"
Anton
Solution simple et facile. Et fonctionne mieux que d'autres solutions dans mon cas bien sûr.
fsevenm
33

J'ai eu le même problème que vous et j'ai fini par créer un plugin jQuery pour en prendre soin. Il résout en fait tous les problèmes que les gens ont énumérés ici, et il ajoute également quelques fonctionnalités optionnelles.

Les 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

Donny V.
la source
1
Hey! Je vous remercie! C'est une excellente solution, et merci pour le partage, c'est sûr que cela m'a fait gagner beaucoup de temps. Cela devrait être la solution globale acceptée pour cette question, car pour autant que je sache, c'est la solution la plus complète. Fondamentalement, les autres n'ont pas résolu le problème avec la position X d'origine d'un bloc après la position: un style fixe est appliqué. Le vôtre résout ce problème. Merci beaucoup!
Marcos Buarque
Hé Donny, j'aime aussi votre plugin (v1.4.1) ... est tombé sur un problème, les éléments de bloc ont perdu leur largeur si aucun n'était spécifié. Il a donc été modifié lors du détachement ... uniquement en réglant la largeur pour qu'il reste le même. code// détache le panneau node.css ({"margin": 0, "left": nodeLeft, "top": newNodeTop, "position": "fixed", "width": node.width ()}); code
Will Hancock
A recherché et essayé de nombreuses solutions, et cela a fonctionné "dès la sortie de la boîte." Travail incroyable! Je vous remercie!
ajtatum
2
@WillHancock J'ai ajouté la prise en charge de l'iPad, corrigé le bogue d'actualisation et ajouté les événements onDetached et onReattached. Les nouveaux événements vous donneront accès au panneau et au panneau d'espacement après son détachement et sa remise en place.
Donny V.
4
Ajout d'une option parentSelector pour prendre en charge les divisions de défilement.
Donny V.
24

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

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>

Jim W dit réintégrer Monica
la source
4
Je vous remercie! Il est difficile de trouver des solutions JS natives de nos jours. Cela a parfaitement fonctionné.
Sherri
Merci beaucoup, cela a parfaitement fonctionné car jquery était en conflit avec un code d'entreprise hérité de mon projet
sng
bien que je rencontre un problème où si je défile vers le bas de la page, il me fera automatiquement remonter en haut.
sng
@sng Mon exemple de page fait-il cela?
Jim W dit réintégrer Monica le
@JimW J'ai découvert le problème. J'essayais de l'utiliser avec une barre de menu verticale à côté d'un div de contenu principal à gauche. Il se dérangeait lorsque vous faites défiler vers le bas car il ne peut pas déterminer quand il atteint correctement le bas de la page. J'ai fini par ajouter une ligne de code pour définir la hauteur de div du conteneur à la taille de l'écran de la fenêtre pour l'écouteur d'événements de défilement
sng
9

C'est comme ça que je l'ai fait avec jquery. Tout cela a été bricolé à partir de diverses réponses sur le débordement de pile. Cette solution met en cache les sélecteurs pour des performances plus rapides et résout également le problème de "saut" lorsque le div collant devient collant.

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);
        }
    });
});
JohnB
la source
7

Voici une autre option:

JAVASCRIPT

var initTopPosition= $('#myElementToStick').offset().top;   
$(window).scroll(function(){
    if($(window).scrollTop() > initTopPosition)
        $('#myElementToStick').css({'position':'fixed','top':'0px'});
    else
        $('#myElementToStick').css({'position':'absolute','top':initTopPosition+'px'});
});

Vous #myElementToStickdevriez commencer par la position:absolutepropriété CSS.

kunde
la source
1
Je pense que c'est une solution très propre et facile. Je ne positionnerais simplement pas l'élément "absolu" - cela pourrait casser la disposition - je le mettrais simplement en statique.
Gerfried
4

Comme l'ont dit Josh Lee et Colin 't Hart , vous pouvez éventuellement utiliser simplement l' position: sticky; top: 0;application à la div que vous souhaitez faire défiler ...

De plus, la seule chose que vous aurez à faire est de la copier en haut de votre page ou de la formater pour qu'elle tienne dans une feuille CSS externe:

<style>
#sticky_div's_name_here { position: sticky; top: 0; }
</style>

Remplacez simplement #sticky_div's_name_herepar le nom de votre div, c'est-à-dire que si votre div était <div id="example">vous mettriez #example { position: sticky; top: 0; }.

KalamariKing
la source
1

Ma solution est un peu détaillée, mais elle gère le positionnement variable à partir du bord gauche pour les mises en page centrées.

// Ensurs that a element (usually a div) stays on the screen
//   aElementToStick   = The jQuery selector for the element to keep visible
global.makeSticky = function (aElementToStick) {
    var $elementToStick = $(aElementToStick);
    var top = $elementToStick.offset().top;
    var origPosition = $elementToStick.css('position');

    function positionFloater(a$Win) {
        // Set the original position to allow the browser to adjust the horizontal position
        $elementToStick.css('position', origPosition);

        // Test how far down the page is scrolled
        var scrollTop = a$Win.scrollTop();
        // If the page is scrolled passed the top of the element make it stick to the top of the screen
        if (top < scrollTop) {
            // Get the horizontal position
            var left = $elementToStick.offset().left;
            // Set the positioning as fixed to hold it's position
            $elementToStick.css('position', 'fixed');
            // Reuse the horizontal positioning
            $elementToStick.css('left', left);
            // Hold the element at the top of the screen
            $elementToStick.css('top', 0);
        }
    }

    // Perform initial positioning
    positionFloater($(window));

    // Reposition when the window resizes
    $(window).resize(function (e) {
        positionFloater($(this));
    });

    // Reposition when the window scrolls
    $(window).scroll(function (e) {
        positionFloater($(this));
    });
};
Josh Russo
la source
1

Voici une autre version à essayer pour ceux qui ont des problèmes avec les autres. Il rassemble les techniques discutées dans cette question en double et génère dynamiquement les DIV d'assistance nécessaires afin qu'aucun HTML supplémentaire ne soit nécessaire.

CSS:

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

JQuery:

function make_sticky(id) {
    var e = $(id);
    var w = $(window);
    $('<div/>').insertBefore(id);
    $('<div/>').hide().css('height',e.outerHeight()).insertAfter(id);
    var n = e.next();
    var p = e.prev();
    function sticky_relocate() {
      var window_top = w.scrollTop();
      var div_top = p.offset().top;
      if (window_top > div_top) {
        e.addClass('sticky');
        n.show();
      } else {
        e.removeClass('sticky');
        n.hide();
      }
    }
    w.scroll(sticky_relocate);
    sticky_relocate();
}

Pour rendre un élément collant, faites:

make_sticky('#sticky-elem-id');

Lorsque l'élément devient collant, le code gère la position du contenu restant pour l'empêcher de sauter dans l'espace laissé par l'élément collant. Il ramène également l'élément collant à sa position non collante d'origine lors du défilement au-dessus de lui.

Dan
la source
Votre approche est très similaire à l'approche de JohnB . Compte tenu de vos différences par rapport à cette réponse, je me demande (1) Y a-t-il un avantage à utiliser un deuxième "helper div" (au lieu d'un seul comme JohnB l'utilise), et (2) Y a-t-il un avantage à utiliser hide () et show () au lieu de simplement définir la hauteur du div assistant (comme le fait JohnB)? Peut-être une différence de performance? Jusqu'à présent, je n'ai pas pu discerner les différences mais peut-être que certains scénarios auraient des différences (comme peut-être impliquant des éléments en ligne ou quelque chose), c'est pourquoi je demande. Merci.
Jason Frank
1

Voici une version étendue de la réponse de Josh Lee. Si vous voulez que le div soit sur la barre latérale à droite et flotte dans une plage (c'est-à-dire, vous devez spécifier les positions d'ancrage supérieure et inférieure). Il corrige également un bogue lorsque vous le visualisez sur des appareils mobiles (vous devez vérifier la position du défilement vers la gauche, sinon le div se déplacera hors de l'écran).

function moveScroller() {
    var move = function() {
        var st = $(window).scrollTop();
        var sl = $(window).scrollLeft();
        var ot = $("#scroller-anchor-top").offset().top;
        var ol = $("#scroller-anchor-top").offset().left;
        var bt = $("#scroller-anchor-bottom").offset().top;
        var s = $("#scroller");
        if(st > ot) {
            if (st < bt - 280) //280px is the approx. height for the sticky div
            {
                s.css({
                    position: "fixed",
                    top: "0px",
                    left: ol-sl
                }); 
            }
            else
            {
                s.css({
                    position: "fixed",
                    top: bt-st-280,
                    left: ol-sl
                }); 
            }
        } else {
            s.css({
                position: "relative",
                top: "",
                left: ""
            });

        }
    };
    $(window).scroll(move);
    move();
}
realwecan
la source
1

Je suis tombé sur cela en cherchant la même chose. Je sais que c'est une vieille question, mais j'ai pensé offrir une réponse plus récente.

Scrollorama a une fonction «pin it» qui est exactement ce que je cherchais.

http://johnpolacek.github.io/scrollorama/

pbryd
la source
0

Les informations fournies pour répondre à cette autre question peuvent vous être utiles, Evan:

Vérifiez si l'élément est visible après le défilement

Vous souhaitez essentiellement modifier le style de l'élément pour le définir sur fixe uniquement après avoir vérifié que la valeur document.body.scrollTop est égale ou supérieure à la partie supérieure de votre élément.

ambre
la source
0

La réponse acceptée fonctionne mais ne revient pas à la position précédente si vous faites défiler au-dessus d'elle. Il est toujours collé au sommet après y avoir été placé.

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

    } else if ($(this).scrollTop() < 42 && $el.css('position') != 'relative') {
      $('.fixedElement').css( 'relative': 'fixed', 'top': '42px');
//this was just my previous position/formating
    }
  });

La réponse de Jleedev devrait fonctionner, mais je n'ai pas réussi à la faire fonctionner. Sa page d'exemple ne fonctionnait pas non plus (pour moi).

Forger
la source
0

Vous pouvez ajouter 3 lignes supplémentaires, donc lorsque l'utilisateur fait défiler vers le haut, le div restera sur son ancien emplacement:

Voici le code:

if ($(this).scrollTop() < 200 && $el.css('position') == 'fixed'){
    $('.fixedElement').css({'position': 'relative', 'top': '200px'});
}
Alex Rashkov
la source
0

J'ai des liens configurés dans un div, c'est donc une liste verticale de liens de lettres et de chiffres.

#links {
    float:left;
    font-size:9pt;
    margin-left:0.5em;
    margin-right:1em;
    position:fixed;
    text-align:center;
    width:0.8em;
}

J'ai ensuite configuré cette fonction jQuery pratique pour enregistrer la position chargée, puis changer la position à fixe lors du défilement au-delà de cette position.

REMARQUE: cela ne fonctionne que si les liens sont visibles au chargement de la page !!

var listposition=false;
jQuery(function(){
     try{
        ///// stick the list links to top of page when scrolling
        listposition = jQuery('#links').css({'position': 'static', 'top': '0px'}).position();
        console.log(listposition);
        $(window).scroll(function(e){
            $top = $(this).scrollTop();
            $el = jQuery('#links');
            //if(typeof(console)!='undefined'){
            //    console.log(listposition.top,$top);
            //}
            if ($top > listposition.top && $el.css('position') != 'fixed'){
                $el.css({'position': 'fixed', 'top': '0px'});
            }
            else if ($top < listposition.top && $el.css('position') == 'fixed'){
                $el.css({'position': 'static'});
            }
        });

    } catch(e) {
        alert('Please vendor [email protected] (Myvendor JavaScript Issue)');
    }
});
Artistan
la source
0

J'ai utilisé une partie du travail ci-dessus pour créer cette technologie. Je l'ai un peu amélioré et j'ai pensé partager mon travail. J'espère que cela t'aides.

Code jsfuddle

function scrollErrorMessageToTop() {
    var flash_error = jQuery('#flash_error');
    var flash_position = flash_error.position();

    function lockErrorMessageToTop() {
        var place_holder = jQuery("#place_holder");
        if (jQuery(this).scrollTop() > flash_position.top && flash_error.attr("position") != "fixed") {
            flash_error.css({
                'position': 'fixed',
                'top': "0px",
                "width": flash_error.width(),
                "z-index": "1"
            });
            place_holder.css("display", "");
        } else {
            flash_error.css('position', '');
            place_holder.css("display", "none");
        }

    }
    if (flash_error.length > 0) {
        lockErrorMessageToTop();

        jQuery("#flash_error").after(jQuery("<div id='place_holder'>"));
        var place_holder = jQuery("#place_holder");
        place_holder.css({
            "height": flash_error.height(),
            "display": "none"
        });
        jQuery(window).scroll(function(e) {
            lockErrorMessageToTop();
        });
    }
}
scrollErrorMessageToTop();​

C'est un peu plus dynamique d'une façon de faire le défilement. Cela nécessite un peu de travail et je vais à un moment donné transformer cela en un plug-in, mais c'est ce que j'ai trouvé après une heure de travail.

newdark-it
la source
0

En javascript, vous pouvez faire:

var element = document.getElementById("myid");
element.style.position = "fixed";
element.style.top = "0%";
Asher
la source
0

Pas une solution exacte mais une excellente alternative à considérer

cette barre de défilement CSS uniquement en haut de l'écran . Résolu tout le problème avec SEULEMENT CSS , AUCUN JavaScript, AUCUN JQuery, aucun travail de cerveau ( lol ).

Profitez de mon violon : D tous les codes y sont inclus :)

CSS

#menu {
position: fixed;
height: 60px;
width: 100%;
top: 0;
left: 0;
border-top: 5px solid #a1cb2f;
background: #fff;
-moz-box-shadow: 0 2px 3px 0px rgba(0, 0, 0, 0.16);
-webkit-box-shadow: 0 2px 3px 0px rgba(0, 0, 0, 0.16);
box-shadow: 0 2px 3px 0px rgba(0, 0, 0, 0.16);
z-index: 999999;
}

.w {
    width: 900px;
    margin: 0 auto;
    margin-bottom: 40px;
}<br type="_moz">

Mettez le contenu assez longtemps pour que vous puissiez voir l'effet ici :) Oh, et la référence est là aussi, car il mérite son crédit

CSS UNIQUEMENT Barre de défilement en haut de l'écran

conception weia
la source
Un peu hors sujet;)
Tokk
Je ne suis pas contre une bonne solution, mais le code dans votre réponse fournit un moyen de faire quelque chose comme un menu pour toujours rester au top. Mais ce n'était pas la question ...
Tokk
vous réparez juste le div et ne faites rien de collant sur le défilement.
yogihosting
0

Voici un exemple qui utilise le plugin jquery-visible: http://jsfiddle.net/711p4em4/ .

HTML:

<div class = "wrapper">
    <header>Header</header>
    <main>
        <nav>Stick to top</nav>
        Content
    </main>
    <footer>Footer</footer>
</div>

CSS:

* {
    margin: 0;
    padding: 0;
}

body {
    background-color: #e2e2e2;
}

.wrapper > header,
.wrapper > footer {
    font: 20px/2 Sans-Serif;
    text-align: center;
    background-color: #0040FF;
    color: #fff;
}

.wrapper > main {
    position: relative;
    height: 500px;
    background-color: #5e5e5e;
    font: 20px/500px Sans-Serif;
    color: #fff;
    text-align: center;
    padding-top: 40px;
}

.wrapper > main > nav {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    font: 20px/2 Sans-Serif;
    color: #fff;
    text-align: center;
    background-color: #FFBF00;
}

.wrapper > main > nav.fixed {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
}

JS (inclut le plugin jquery-visible):

(function($){

    /**
     * Copyright 2012, Digital Fusion
     * Licensed under the MIT license.
     * http://teamdf.com/jquery-plugins/license/
     *
     * @author Sam Sehnert
     * @desc A small plugin that checks whether elements are within
     *       the user visible viewport of a web browser.
     *       only accounts for vertical position, not horizontal.
     */
    var $w = $(window);
    $.fn.visible = function(partial,hidden,direction){

        if (this.length < 1)
            return;

        var $t        = this.length > 1 ? this.eq(0) : this,
            t         = $t.get(0),
            vpWidth   = $w.width(),
            vpHeight  = $w.height(),
            direction = (direction) ? direction : 'both',
            clientSize = hidden === true ? t.offsetWidth * t.offsetHeight : true;

        if (typeof t.getBoundingClientRect === 'function'){

            // Use this native browser method, if available.
            var rec = t.getBoundingClientRect(),
                tViz = rec.top    >= 0 && rec.top    <  vpHeight,
                bViz = rec.bottom >  0 && rec.bottom <= vpHeight,
                lViz = rec.left   >= 0 && rec.left   <  vpWidth,
                rViz = rec.right  >  0 && rec.right  <= vpWidth,
                vVisible   = partial ? tViz || bViz : tViz && bViz,
                hVisible   = partial ? lViz || rViz : lViz && rViz;

            if(direction === 'both')
                return clientSize && vVisible && hVisible;
            else if(direction === 'vertical')
                return clientSize && vVisible;
            else if(direction === 'horizontal')
                return clientSize && hVisible;
        } else {

            var viewTop         = $w.scrollTop(),
                viewBottom      = viewTop + vpHeight,
                viewLeft        = $w.scrollLeft(),
                viewRight       = viewLeft + vpWidth,
                offset          = $t.offset(),
                _top            = offset.top,
                _bottom         = _top + $t.height(),
                _left           = offset.left,
                _right          = _left + $t.width(),
                compareTop      = partial === true ? _bottom : _top,
                compareBottom   = partial === true ? _top : _bottom,
                compareLeft     = partial === true ? _right : _left,
                compareRight    = partial === true ? _left : _right;

            if(direction === 'both')
                return !!clientSize && ((compareBottom <= viewBottom) && (compareTop >= viewTop)) && ((compareRight <= viewRight) && (compareLeft >= viewLeft));
            else if(direction === 'vertical')
                return !!clientSize && ((compareBottom <= viewBottom) && (compareTop >= viewTop));
            else if(direction === 'horizontal')
                return !!clientSize && ((compareRight <= viewRight) && (compareLeft >= viewLeft));
        }
    };

})(jQuery);

$(function() {
    $(window).scroll(function() {
        $(".wrapper > header").visible(true) ?
            $(".wrapper > main > nav").removeClass("fixed") :
            $(".wrapper > main > nav").addClass("fixed");
    });
});
DRD
la source
-1

collant jusqu'à ce que le pied de page frappe la div:

function stickyCostSummary() {
    var stickySummary = $('.sticky-cost-summary');
    var scrollCostSummaryDivPosition = $(window).scrollTop();
    var footerHeight = $('#footer').height();
    var documentHeight = $(document).height();
    var costSummaryHeight = stickySummary.height();
    var headerHeight = 83;
    var footerMargin = 10;
    var scrollHeight = 252;
    var footerPosition = $('#footer').offset().top;

    if (scrollCostSummaryDivPosition > scrollHeight && scrollCostSummaryDivPosition <= (documentHeight - footerHeight - costSummaryHeight - headerHeight - footerMargin)) {
        stickySummary.removeAttr('style');
        stickySummary.addClass('fixed');

    } else if (scrollCostSummaryDivPosition > (documentHeight - footerHeight - costSummaryHeight - headerHeight - footerMargin)) {
        stickySummary.removeClass('fixed');
        stickySummary.css({
          "position" : "absolute",
          "top" : (documentHeight - footerHeight - costSummaryHeight - headerHeight - footerMargin - scrollHeight) + "px"
      });
    } else {
        stickySummary.removeClass('fixed');
        stickySummary.css({
            "position" : "absolute",
            "top" : "0"
        });
    }
}

$window.scroll(stickyCostSummary);
Ottens
la source