Come posso fare un div stick nella parte superiore dello schermo dopo averlo fatto scorrere?


305

Vorrei creare un div, che si trova sotto un blocco di contenuti, ma che una volta che la pagina è stata sufficientemente scrollata per contattare il suo limite superiore, si fissa sul posto e scorre con la pagina.


5
A partire da giugno 2014, il plug-in jQuery Sticky-kit è una delle opzioni più semplici, fornendo una barriera estremamente bassa all'ingresso e molte funzionalità. Ottimo punto di partenza se stai cercando un modo semplice per scendere rapidamente da terra.
user456584,


32
L'aggiunta di CSS position: sticky; top:0;funziona nella maggior parte dei browser a gennaio 2017.
Colin 't Hart

9
Santa merda, quella position: sticky;cosa è magica.
salta il

Risposte:


259

Puoi usare semplicemente css, posizionando il tuo elemento come fisso :

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

Modifica: dovresti avere l'elemento con posizione assoluta, una volta che l'offset di scorrimento ha raggiunto l'elemento, dovrebbe essere cambiato in fisso e la posizione in alto dovrebbe essere impostata su zero.

È possibile rilevare l'offset di scorrimento superiore del documento con la funzione 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'}); 
  } 
});

Quando l'offset di scorrimento ha raggiunto 200, l'elemento si attaccherà nella parte superiore della finestra del browser, poiché è posizionato come fisso.


4
ciò non ottiene ciò che sto cercando. Vorrei che l'elemento iniziasse a 200px sotto la parte superiore della pagina (per consentire spazio per altri contenuti) e poi, una volta che l'utente ha fatto scorrere verso il basso, si fissa nella parte superiore.
evanr,

3
la tua modifica soddisfa davvero le esigenze della domanda ora ma hai ancora problemi quando la pagina torna di nuovo all'inizio. potresti aver raggiunto l'elemento scrollTop memorizzarlo da qualche parte, e quando la pagina colpisce di nuovo quella posizione (quando si scorre verso l'alto) riportare i CSS di default ... probabilmente è meglio farlo con una .toggleClass quindi ...
Sander

9
Questo è praticamente quello che succede con ma ho dovuto rimuovere il posizionamento fisso quando la finestra is è tornata in alto. if ($(this).scrollTop() < 200 && $el.css('position') == 'fixed') { $('.fixedElement').css({'position': 'static', 'top': '0px'}); }
Derrick Petzold,

1
@DerrickPetzold L'ho messo nella risposta, cose piuttosto importanti :)
MarioDS,

1
il new examplelink che hai dato è così pulito e chiaro che non riesco nemmeno a vederlo! -_-
sohaiby

245

Hai visto questo esempio nella pagina dei problemi di Google Code e (solo di recente) nella pagina di modifica di Stack Overflow.

La risposta di CMS non ripristina il posizionamento quando si scorre indietro. Ecco il codice spudoratamente rubato da 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> 

E una semplice demo dal vivo .

Un'alternativa nascente e senza script position: stickyè supportata in Chrome, Firefox e Safari. Vedi l' articolo su HTML5Rocks e demo e i documenti di Mozilla .


3
Per qualche ragione, {scroll: false} mi stava dando problemi (jQuery 1.6.2). Sembra funzionare senza di essa. Fork dalla demo collegata. Qualche idea se serve a uno scopo?
Eddie,

Sto avendo molti problemi con questo, per la vita di me che non riesco a replicare, ho anche provato a replicare la demo dal vivo e il suo non funziona. qualcuno può collegarsi a un tutorial che fornisce istruzioni dettagliate?
Trevor Dupp,

2
Questo sembra funzionare bene, quando uso la stessa versione di jQuery della demo (1.3.2). Ad un certo punto offsetdeve aver smesso di accettare un oggetto come input api.jquery.com/offset . @Eddie La tua modifica dovrebbe essere sicura con l'attuale jQuery.
Graeme,

1
C'è qualche ragione per cui non si potrebbe sostituire var d = $("#scroller-anchor").offset().top;con var d = $("#sidebar").offset().top;e sbarazzarsi del vuoto div scroller-ancora tutti insieme? Ecco la mia forchetta che dimostra di cosa sto parlando.
Mike Deck,

@MikeDeck Ho il sospetto che se ci sono margini o imbottiture, vorresti poter controllare dove è posizionato lo scroller rispetto al contenitore.
Josh Lee,

72

A partire da gennaio 2017 e dal rilascio di Chrome 56, la maggior parte dei browser di uso comune supporta la position: stickyproprietà nei CSS.

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

fa il trucco per me in Firefox e Chrome.

In Safari devi ancora usare position: -webkit-sticky.

Polyfill sono disponibili per Internet Explorer e Edge; https://github.com/wilddeer/stickyfill sembra essere una buona scelta.


5
Questo è supportato nella maggior parte dei browser di uso comune oggi. Vedi caniuse.com/#feat=css-sticky In secondo luogo, preferisco di gran lunga una soluzione che può essere ridotta a 2 righe di codice a una versione che richiede Javascript personalizzato. Ed è anche a prova di futuro. Usa un polyfill se sei preoccupato per la compatibilità del browser.
Colin 't Hart,

1
Non può essere più facile di così :)
avviato il

1
Vorrei aggiungere a questo commento che possiamo z-index: 99999 ;, perché se non quando va in cima, l'altro contenuto verrà visualizzato per primo. Ma questa dovrebbe essere la soluzione accettata.
dayanrr91,

Basta avvolgerlo in un div con id = "thing_to_stick"
Anton

Soluzione semplice e facile. E funziona meglio di altre soluzioni nel mio caso, ovviamente.
fsevenm,

33

Ho avuto lo stesso problema con te e ho finito per creare un plugin jQuery per occuparmene. In realtà risolve tutti i problemi che le persone hanno elencato qui, inoltre aggiunge un paio di funzionalità opzionali.

Opzioni

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

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


1
Hey! Grazie! Questa è un'ottima soluzione, e grazie per la condivisione, sicuramente mi ha fatto risparmiare un sacco di tempo. Questa dovrebbe essere la soluzione complessivamente accettata per questa domanda, dal momento che per quanto ho letto, è la soluzione più completa. Fondamentalmente, gli altri non hanno risolto il problema con la posizione X originale di un blocco dopo la posizione: viene applicato lo stile fisso. Il tuo risolve questo problema. Davvero, molte grazie!
Marcos Buarque,

Ehi Donny, adoro anche il tuo plugin (v1.4.1) ... si è verificato un problema, gli elementi di blocco hanno perso la loro larghezza se non ne è stato specificato nessuno. Così modificato durante il distacco ... solo impostando la larghezza in modo che rimanga lo stesso. code// staccare panel node.css ({"margin": 0, "left": nodeLeft, "top": newNodeTop, "position": "fixed", "width": node.width ()}); code
Will Hancock il

Ho cercato e provato molte soluzioni, e questo ha funzionato "subito pronto all'uso". Lavoro fantastico! Grazie!
ajtatum,

2
@WillHancock Ho aggiunto il supporto per iPad, corretto il bug di aggiornamento e aggiunto gli eventi onDetached e onReattached. I nuovi eventi ti daranno accesso al pannello e al pannello spaziatore dopo che è stato rimosso e ricollegato.
Donny V.

4
Aggiunta anche un'opzione parentSelector per supportare div a scorrimento.
Donny V.,

24

Ed ecco come senza jquery (AGGIORNAMENTO: vedi altre risposte dove ora puoi farlo solo con CSS)

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
Grazie! Oggigiorno è difficile trovare soluzioni JS native. Questo ha funzionato perfettamente.
Sherri,

Grazie mille, ha funzionato perfettamente poiché jquery era in conflitto con un codice aziendale legacy del mio progetto
sng

anche se sto incontrando un problema in cui se scorro fino alla fine della pagina, mi riporterà automaticamente in alto.
Sng

@sng La mia pagina di esempio lo fa?
Jim W dice di ripristinare Monica il

@JimW Ho scoperto il problema. Stavo cercando di usarlo con una barra dei menu basata verticale accanto a un div contenuto principale a sinistra. Stava dando fastidio quando scorri verso il basso poiché non è in grado di determinare quando sta colpendo correttamente la parte inferiore della pagina. Ho finito per aggiungere una riga di codice per impostare l'altezza div del contenitore per la dimensione dello schermo della finestra per il listener di eventi scroll
sng

9

È così che l'ho fatto con jquery. Tutto questo è stato messo insieme da varie risposte sullo overflow dello stack. Questa soluzione memorizza nella cache i selettori per prestazioni più veloci e risolve anche il problema del "salto" quando il div appiccicoso diventa appiccicoso.

Dai un'occhiata su 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);
        }
    });
});

7

Ecco un'altra opzione:

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

Il tuo #myElementToStickdovrebbe iniziare con position:absoluteproprietà CSS.


1
Penso che questa sia una soluzione molto semplice e pulita. Semplicemente non posizionerei l'elemento "assoluto" - questo potrebbe spezzare il layout - lo imposterei semplicemente su statico.
Gerfried,

4

Come hanno detto Josh Lee e Colin 't Hart , si può semplicemente usareposition: sticky; top: 0; applicazione al div in cui vuoi scorrere ...

Inoltre, l'unica cosa che dovrai fare è copiarlo nella parte superiore della tua pagina o formattarlo per adattarlo a un foglio CSS esterno:

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

Sostituisci semplicemente #sticky_div's_name_herecon il nome del tuo div, cioè se il tuo div fosse <div id="example">lo avresti messo #example { position: sticky; top: 0; }.


1

La mia soluzione è un po 'dettagliata, ma gestisce il posizionamento variabile dal bordo sinistro per layout centrati.

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

1

Ecco un'altra versione da provare per chi ha problemi con gli altri. Riunisce le tecniche discusse in questa duplice domanda e genera dinamicamente i DIV helper richiesti, quindi non è necessario HTML aggiuntivo.

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

Per rendere un elemento appiccicoso, fai:

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

Quando l'elemento diventa appiccicoso, il codice gestisce la posizione del contenuto rimanente per evitare che salti nello spazio lasciato dall'elemento appiccicoso. Riporta anche l'elemento adesivo nella sua posizione non appiccicosa originale quando si scorre indietro sopra di esso.


Il tuo approccio è molto simile a l'approccio di JohnB . Considerando le tue differenze rispetto a quella risposta, mi chiedo (1) C'è un vantaggio nell'usare un secondo "helper div" (invece di solo 1 come JohnB usa), e (2) C'è un vantaggio nell'usare hide () e show () invece di impostare semplicemente l'altezza del div helper (come fa JohnB)? Forse una differenza di prestazioni? Finora non sono stato in grado di discernere le differenze, ma forse alcuni scenari avrebbero differenze (come forse coinvolgere elementi in linea o qualcosa del genere), quindi è per questo che chiedo. Grazie.
Jason Frank,

1

Ecco una versione estesa alla risposta di Josh Lee. Se si desidera che il div si trovi sulla barra laterale a destra e fluttui all'interno di un intervallo (cioè, è necessario specificare le posizioni di ancoraggio superiore e inferiore). Risolve anche un bug quando lo visualizzi su dispositivi mobili (devi controllare la posizione di scorrimento a sinistra altrimenti il ​​div si sposterà fuori dallo schermo).

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

1

Mi sono imbattuto in questo quando cercavo la stessa cosa. So che è una vecchia domanda, ma ho pensato di offrire una risposta più recente.

Scrollorama ha una funzione "pin it" che è proprio quello che stavo cercando.

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


0

Le informazioni fornite per rispondere a questa altra domanda potrebbero esserti di aiuto, Evan:

Controlla se l'elemento è visibile dopo lo scorrimento

Fondamentalmente si desidera modificare lo stile dell'elemento per impostarlo su fixed solo dopo aver verificato che il valore document.body.scrollTop sia uguale o maggiore della parte superiore dell'elemento.


0

La risposta accettata funziona ma non torna alla posizione precedente se si scorre sopra di essa. È sempre bloccato in cima dopo essere stato posizionato lì.

  $(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 risposta di jleedev avrebbe funzionato, ma non sono riuscito a farlo funzionare. Anche la sua pagina di esempio non ha funzionato (per me).


0

Puoi aggiungere 3 righe extra in modo che quando l'utente torna indietro, il div si attaccherà al suo posto precedente:

Ecco il codice:

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

0

Ho impostato i collegamenti in un div, quindi è un elenco verticale di collegamenti di lettere e numeri.

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

Ho quindi impostato questa pratica funzione jQuery per salvare la posizione caricata e quindi cambiare la posizione in fissa quando si scorre oltre quella posizione.

NOTA: funziona solo se i link sono visibili al caricamento della pagina !!

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 admin@mydomain.com (Myvendor JavaScript Issue)');
    }
});

0

Ho usato parte del lavoro sopra per creare questa tecnologia. L'ho migliorato un po 'e ho pensato di condividere il mio lavoro. Spero che questo ti aiuti.

Codice 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();​

Questo è un po 'più dinamico di un modo per fare lo scroll. Ha bisogno di un po 'di lavoro e ad un certo punto lo trasformerò in un plug-in, ma questo è quello che mi è venuto in mente dopo un'ora di lavoro.


0

In javascript puoi fare:

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

0

Non una soluzione esatta ma un'ottima alternativa da considerare

questo CSS SOLO nella parte superiore della barra di scorrimento dello schermo . Risolto tutto il problema con SOLO CSS , NO JavaScript, NO JQuery, No Brain work ( lol ).

Goditi il mio violino : D tutti i codici sono inclusi lì :)

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">

Metti il ​​contenuto abbastanza a lungo in modo da poter vedere l'effetto qui :) Oh, e il riferimento è anche lì, per il fatto che merita il suo credito

SOLO CSS Barra di scorrimento superiore dello schermo


Un po 'offtopico;)
Tokk

Non sono contrario a una buona soluzione, ma il codice nella tua risposta fornisce un modo per creare qualcosa come un menu per rimanere sempre in primo piano. Ma non era questa la domanda ...
Tokk,

stai solo aggiustando il div e non stai facendo nulla di appiccicoso sullo scorrimento.
Yogihosting

0

Ecco un esempio che utilizza il 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 (include 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");
    });
});

-1

appiccicoso fino a quando il footer non colpisce il 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);
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.