"Posizione: appiccicosa;" CSS e HTML non funzionanti


177

Voglio far aderire la barra di navigazione verso l'alto una volta che la scorro, ma non funziona e non ho idea del perché. Se puoi aiutarmi, ecco il mio codice HTML e CSS:

.nav-selections {
  text-transform: uppercase;
  letter-spacing: 5px;
  font: 18px "lato",sans-serif;
  display: inline-block;
  text-decoration: none;
  color: white;
  padding: 18px;
  float: right;
  margin-left: 50px;
  transition: 1.5s;
}

.nav-selections:hover{
  transition: 1.5s;
  color: black;
}

ul {
  background-color: #B79b58;
  overflow: auto;
}

li {
  list-style-type: none;
}
<nav style="position: sticky; position: -webkit-sticky;">
  <ul align="left">
    <li><a href="#/contact" class="nav-selections" style="margin-right:35px;">Contact</a></li>
    <li><a href="#/about" class="nav-selections">About</a></li>
    <li><a href="#/products" class="nav-selections">Products</a></li>
    <li><a href="#" class="nav-selections">Home</a></li>
  </ul>
</nav>


10
posizione: appiccicoso ha bisogno di un coordinato per tel dove attaccare
G-Cyrillus

36
Devi anche stare attento con gli elementi padre. position: stickypuò smettere di funzionare se è all'interno di un flexbox a meno che tu non stia attento e fallirà anche se c'è uno overflow: hiddeno overflow: autotra di esso e qualunque cosa scorra all'interno (radice del corpo o antenato più vicino con overflow: scroll)
user56reinstatemonica8

2
@ user56reinstatemonica8 OMG grazie mille per avermi parlato di overflow: hiddene overflow: auto! Ho grattato la testa per giorni cercando di far funzionare questa merda
Oneezy il

Risposte:


206

Il posizionamento appiccicoso è un ibrido di posizionamento relativo e fisso. L'elemento viene trattato come posizionato relativo fino a quando non supera una soglia specificata, a quel punto viene trattato come posizionato fisso.
...
È necessario specificare una soglia di almeno una delle top, right, bottom, o leftper il posizionamento appiccicosa a comportarsi come previsto. Altrimenti, sarà indistinguibile dal posizionamento relativo. [ fonte: MDN ]

Quindi nel tuo esempio, devi definire la posizione in cui dovrebbe rimanere alla fine usando la topproprietà.

html, body {
  height: 200%;
}

nav {
  position: sticky;
  position: -webkit-sticky;
  top: 0; /* required */
}

.nav-selections {
  text-transform: uppercase;
  letter-spacing: 5px;
  font: 18px "lato", sans-serif;
  display: inline-block;
  text-decoration: none;
  color: white;
  padding: 18px;
  float: right;
  margin-left: 50px;
  transition: 1.5s;
}

.nav-selections:hover {
  transition: 1.5s;
  color: black;
}

ul {
  background-color: #B79b58;
  overflow: auto;
}

li {
  list-style-type: none;
}
<nav>
  <ul align="left">
    <li><a href="#/contact" class="nav-selections" style="margin-right:35px;">Contact</a></li>
    <li><a href="#/about" class="nav-selections">About</a></li>
    <li><a href="#/products" class="nav-selections">Products</a></li>
    <li><a href="#" class="nav-selections">Home</a></li>
  </ul>
</nav>


124
In generale, questa risposta non è sufficiente per funzionare, anche il genitore non dovrebbe avere proprietà di overflow.
ViliusL

Grazie per il tuo commento. Concordo con te sul fatto che per esempi diversi da quelli del PO la mia risposta potrebbe non essere sufficiente. Le altre risposte lo sottolineano :)
Marvin,

Penso che il trucco sia che la posizione appiccicosa può essere applicata solo ai bambini che appartengono a un genitore scorrevole con un'altezza nota (un bambino diretto in un flexbox ha un'altezza nota calcolata da un altro oggetto flessibile)
code4j

@ViliusL grazie per il tuo commento! Quello era il problema che avevo con la posizione: appiccicoso, non avrei saputo che se non fosse stato per te, poiché non ho trovato queste informazioni da nessuna parte.
Piotr Szlagura,

sticky position non dovrebbe avere un genitore con proprietà di overflow, inoltre sticky non è supportato in alcuni browser Web
Rohan Shenoy,

331

Verifica se un elemento antenato ha impostato l'overflow (ad es. overflow:hidden); prova ad attivarlo. Potrebbe essere necessario salire l'albero del DOM più in alto di quanto ci si aspetti =).

Ciò può influire position:stickysu un elemento discendente.


36
Vorrei poterti votare più volte! Questo mi ha morso più spesso di quanto mi piacerebbe ammettere.
Alexander Varwijk,

2
Questa è la risposta esatta. Tuttavia, può essere difficile trovare quale elemento genitore sta causando il problema. Ho scritto uno script jquery per aiutare a identificare la proprietà di overflow sui genitori che ha identificato il problema (basta eseguirlo nella tua console). Poiché lo script è composto da poche righe, ho aggiunto una risposta contenente lo script seguente.
danday74

5
Mi mancava la "s" nei tuoi "elementi genitori"
che-azeh,

5
Ho anche perso la "s" :( e quello era il problema. In molti posti le persone scrivono che dovresti controllare solo i genitori non tutti i genitori. Ho trovato il mio problema controllando se chiamare $(stickyElement).parents().css("overflow", "visible")nella console web avrebbe aiutato e lo ha fatto. Poi ho individuato il genitore distante con overflow:hiddenstile che ha causato il problema. Vorrei leggere più attentamente questa risposta.
Mariusz Pawelski

2
Se hai bisogno di controllare overflow:hidden, puoi eseguire questo script nella tua console del browser per controllare tutti i genitori / antenati di un dato elemento: gist.github.com/brandonjp/478cf6e32d90ab9cb2cd8cbb0799c7a7
brandonjp

100

Ho lo stesso problema e ho trovato la risposta qui .

Se il tuo elemento non si attacca come previsto, la prima cosa da controllare sono le regole applicate al contenitore.

In particolare, cercare eventuali proprietà di overflow impostate sul padre. Non è possibile utilizzare : overflow: hidden, overflow: scrollo overflow: autosul genitore di un position: stickyelemento.


Questa è anche la risposta giusta, ma vedi anche la mia risposta che aiuta a identificare facilmente il genitore che causa il problema.
danday74

10
Si dovrebbe controllare non solo contenitore principale più vicina, ma tutti i elemento padre s .
Mariusz Pawelski,

sì, vedi la mia risposta per fare esattamente questo e controlla TUTTI i genitori molto rapidamente
danday74

1
Anche il link mi ha aiutato. Il mio problema è stato risolto da "... Se non stai usando il troppopieno e continui ad avere problemi, vale la pena controllare se è impostata un'altezza sul genitore ..."
xenetics,

Risparmio di vita, descrizione davvero semplice del problema, ma c'è un modo per aggirare questo curioso
Rahul Singh,

32

Poche altre cose che ho incontrato:

Quando il tuo elemento adesivo è un componente (angolare ecc.)

  • Se l'elemento 'appiccicoso' stesso è un componente con un selettore di elementi personalizzato, come un componente angolare denominato <app-menu-bar>, sarà necessario aggiungere quanto segue al CSS del componente:

    :host { display: block; }   

    o

    app-menu-bar  { display: block; }   // (in the containing component's css)

    Safari su iOS in particolare sembra richiedere display:blockanche sull'elemento radice app-rootdi un'applicazione angolare o non si attaccherà.

  • Se stai creando un componente e definendo i CSS all'interno del componente (DOM shadow / stili incapsulati), assicurati che position: stickysia applicato al selettore 'esterno' (ad es. app-menu-barIn devtools dovrebbe mostrare la posizione appiccicosa) e non un livello superiore div all'interno il componente. Con Angular, questo può essere ottenuto con il :hostselettore nel CSS per il componente.

    :host
    {
        position: sticky;
        display: block;   // this is the same as shown above
        top: 0;
        background: red;    
    }

Altro

  • Se l'elemento che segue l'elemento adesivo ha uno sfondo solido, è necessario aggiungere quanto segue per impedirne lo scorrimento al di sotto:

    .sticky-element { z-index: 100; }
    .parent-of-sticky-element { position: relative; }
  • L'elemento adesivo deve essere il primo (prima del contenuto) se lo si utilizza tope dopo se lo si utilizza bottom.

  • Ci sono complicazioni quando si utilizza overflow: hiddensull'elemento wrapper - in generale ucciderà l'elemento appiccicoso all'interno. Meglio spiegato in questa domanda

  • I browser mobili possono disabilitare gli oggetti appiccicosi / fissi posizionati quando è visibile la tastiera su schermo. Non sono sicuro delle regole esatte (qualcuno lo sa mai) ma quando la tastiera è visibile stai osservando una sorta di "finestra" nella finestra e non sarai in grado di far sì che le cose si attacchino al parte superiore visibile effettiva dello schermo.

  • Assicurati di avere:

    position: sticky;

    e non

    display: sticky;

Varie preoccupazioni sull'usabilità

  • Fai attenzione se il tuo progetto richiede di attaccare oggetti nella parte inferiore dello schermo sui dispositivi mobili. Ad esempio, su iPhone X viene visualizzata una linea stretta per indicare la regione di scorrimento (per tornare alla home page) - e gli elementi all'interno di questa regione non sono selezionabili. Quindi, se attacchi qualcosa, assicurati di testare su iPhone X che gli utenti possano attivarlo. Un grande pulsante 'Acquista ora' non va bene se le persone non possono fare clic!
  • Se fai pubblicità su Facebook, la pagina web viene visualizzata in un controllo "visualizzazione Web" all'interno delle app mobili di Facebook. Soprattutto quando si visualizzano video (in cui il contenuto inizia solo nella metà inferiore dello schermo), spesso confondono completamente gli elementi appiccicosi inserendo la pagina in una finestra scorrevole che in realtà consente agli elementi appiccicosi di scomparire dalla parte superiore della pagina. Assicurati di testare nel contesto di un annuncio reale e non solo nel browser del telefono o persino nel browser di Facebook che possono comportarsi in modo diverso.

@Sergey Non sono assolutamente chiaro di quale display: blocksia position: relativeil comportamento corretto in Safari e sembra che display: blockfosse necessario solo ? Ovviamente probabilmente non fa male specificare entrambi
Simon_Weaver,

2
Basta display: blockera abbastanza
Sergey

27

Questa è una continuazione delle risposte di MarsAndBack e Miftah Mizwar.

Le loro risposte sono corrette. Tuttavia, è difficile identificare gli antenati problematici.

Per renderlo molto semplice, esegui semplicemente questo script jQuery nella tua console del browser e ti dirà il valore della proprietà overflow su ogni antenato.

$('.your-sticky-element').parents().filter(function() {
    console.log($(this));
    console.log($(this).css('overflow'));
    return $(this).css('overflow') === 'hidden';
});

Dove un antenato non ha overflow: visiblecambiato il suo CSS in modo che lo faccia!

Inoltre, come indicato altrove, assicurati che il tuo elemento appiccicoso abbia questo nel CSS:

.your-sticky-element {
    position: sticky;
    top: 0;
}

2
È stato molto utile. Sono stato in grado di identificare rapidamente l'elemento genitore che aveva un valore di overflow: invisible.
David Brower,

4
Se non hai jQuery sulla tua pagina, puoi eseguire questo piccolo frammento nella console per aggiungerlo: (async function() { let response = await fetch('https://code.jquery.com/jquery-3.3.1.min.js'); let script = await response.text(); eval(script); })();
magikMaker

8
Puoi anche eseguire questo frammento che non richiede a JQuery di trovare un genitore di overflow non "visibile": var p = $0.parentElement; while(p != null) { var ov = getComputedStyle(p).overflow; if(ov !== 'visible') console.warn(ov, p); else console.log(ov, p); p = p.parentElement; }dove $0è l' ultimo elemento selezionato negli strumenti di sviluppo.
Mariusz Pawelski,

Si potrebbe anche gestire position: fixede appropriare le proprietà con JavaScript. La domanda non afferma la necessità di JavaScript.
vintproykt

12

Ho dovuto usare il seguente CSS per farlo funzionare:

.parent {
    display: flex;
    justify-content: space-around;
    align-items: flex-start;
    overflow: visible;
}

.sticky {
    position: sticky;
    position: -webkit-sticky;
    top: 0;
}

Se sopra non funziona, allora ...

Passa attraverso tutti gli antenati e assicurati che nessuno di questi elementi abbia overflow: hidden. Devi cambiare questo inoverflow: visible


1
display: flex rende la cosa
MaciejLisCK

6

Nel caso in cui ti sia imbattuto in questo e il tuo sticky non funzioni, prova a impostare il genitore su:

display: unset

Ha funzionato per me


Questo è quello.
mm-93,

Oh! Questo sembra essere un modo per aggirare il caso in cui un elemento genitore abbia un'altezza limitata (ad esempio un contenitore della barra di navigazione o qualcosa del genere, al contrario di un intero corpo o contenitore di pagine) - sembra che agli sticky non piaccia scorrere al di fuori del loro genitori (il che è assolutamente ridicolo!) Ora tutti hanno solo bisogno di essere così fortunati da essere in grado di impostare il genitore display: unset, il che potrebbe non essere sempre immediatamente praticabile
Ben Philipp,

Sembra anche a lavorare con contents, initiale (?)inline
Ben Philipp

5

Momento divertente che non era ovvio per me: almeno in Chrome 70 position: stickynon viene applicato se lo hai impostato utilizzando DevTools.


Hai una fonte per questo o altre informazioni su come aggirare questo?
AJMansfield,

5

Sembra che la barra di navigazione da incollare non dovrebbe trovarsi all'interno di div o sezioni con altri contenuti. Nessuna delle soluzioni funzionava per me fino a quando non ho tolto la barra di navigazione dal div che la barra di navigazione condivideva con un'altra barra superiore. In precedenza avevo barra superiore e barra di navigazione avvolta con un div comune.


Grazie, questo era quello che stavo cercando! Per me non c'erano genitori con troppopieno, né problemi di altezza. Sarebbe bello vedere anche queste informazioni nella risposta accettata.
saglamcem,

Ho appena scoperto sperimentando che l'adesivo non scorre all'esterno del suo elemento genitore. Non ha molta importanza quanti altri fratelli ha, ma a quanto pare il suo genitore non può essere un contenitore di barra di navigazione ma deve essere qualcosa al livello di un contenitore di pagine / contenuti :( Questo è ridicolo
Ben Philipp

Ma Lo! Se puoi, se imposti il ​​genitore limitatore su display: unset, questa limitazione viene revocata! vedi stackoverflow.com/a/60560997/2902367 Sembra funzionare anche con contents, initial(?) einline
Ben Philipp

4

dal mio commento:

position:sticky ha bisogno di un coordinato per tel dove attaccare

nav {
  position: sticky;
  top: 0;
}

.nav-selections {
  text-transform: uppercase;
  letter-spacing: 5px;
  font: 18px "lato", sans-serif;
  display: inline-block;
  text-decoration: none;
  color: white;
  padding: 18px;
  float: right;
  margin-left: 50px;
  transition: 1.5s;
}

.nav-selections:hover {
  transition: 1.5s;
  color: black;
}

ul {
  background-color: #B79b58;
  overflow: auto;
}

li {
  list-style-type: none;
}

body {
  height: 200vh;
}
<nav>
  <ul align="left">
    <li><a href="#/contact" class="nav-selections" style="margin-right:35px;">Contact</a></li>
    <li><a href="#/about" class="nav-selections">About</a></li>
    <li><a href="#/products" class="nav-selections">Products</a></li>
    <li><a href="#" class="nav-selections">Home</a></li>
  </ul>
</nav>

Esiste un polyfill da utilizzare per browser diversi da FF e Chrome. Si tratta di regole sperimentali che possono essere implementate o meno in qualsiasi momento tramite i browser. Chrome lo ha aggiunto un paio di anni fa e poi lo ha lasciato cadere, sembra tornato ... ma per quanto tempo?

Il più vicino sarebbe position: relative + coordonates aggiornati durante lo scorrimento una volta raggiunto il punto critico, se vuoi trasformarlo in uno script javascript


4

So che sembra che abbia già ricevuto risposta, ma mi sono imbattuto in un caso specifico e sento che molte risposte mancano il punto.

Le overflow:hiddenrisposte coprono il 90% dei casi. Questo è più o meno lo scenario "appiccicoso nav".

Ma il comportamento appiccicoso è meglio utilizzato all'altezza di un contenitore. Pensa a un modulo newsletter nella colonna di destra del tuo sito Web che scorre verso il basso con la pagina. Se il tuo elemento adesivo è l'unico figlio del contenitore, il contenitore ha le stesse dimensioni esatte e non c'è spazio per scorrere.

Il tuo contenitore deve essere l'altezza che ti aspetti che il tuo elemento scorra all'interno. Che nel mio scenario "colonna destra" è l'altezza della colonna sinistra. Il modo migliore per raggiungere questo obiettivo è utilizzare display:table-cellle colonne. Se non puoi, e sei bloccato float:righte come me, dovresti indovinare l'altezza della colonna di sinistra per calcolarlo con Javascript.


2
"Se l'elemento adesivo è l'unico figlio del contenitore, il contenitore ha le stesse dimensioni esatte e non c'è spazio per lo scorrimento." ORO!!! Grazie!
Mark Jackson il

Sì! Mi ci è voluto un po 'per capire questo. All'inizio l'ho trovata una ridicola limitazione, ma suppongo che ci dovrebbe essere almeno l' opzione per quello. Preferirei di gran lunga qualcosa del genere sticky-limit: parent, sticky-limit: bodyo sticky-limit: nth-parent(3)... Comunque: se puoi, puoi sollevare questa limitazione impostando il genitore limitatore su display: unset, come notato in stackoverflow.com/a/60560997/2902367 . Sembra anche a lavorare con contents, initiale (?)inline
Ben Philipp

3

So che questo è un vecchio post. Ma se c'è qualcuno come me che di recente ha iniziato a scherzare con la posizione: appiccicoso questo può essere utile.

Nel mio caso stavo usando position: appiccicoso come un oggetto a griglia. Non funzionava e il problema era un overflow-x: nascosto htmlsull'elemento. Non appena ho rimosso quella proprietà ha funzionato bene. Avere overflow-x: nascosto bodysull'elemento sembrava funzionare, non so ancora perché.


1

due risposte qui:

  1. rimuovere la overflowproprietà dal bodytag

  2. impostato height: 100%su bodyper risolvere il problema conoverflow-y: auto

min-height: 100% non funzionante invece di height: 100%


1

Credo che questo articolo dica molto su come stickyfunziona

Come funziona davvero la posizione CSS appiccicosa! La posizione CSS appiccicosa ha due parti principali, oggetto appiccicoso e contenitore appiccicoso .

Sticky Item  - è l'elemento che abbiamo definito con la posizione: stili appiccicosi. L'elemento galleggerà quando la posizione finestra corrisponde alla definizione di posizione, ad esempio: top: 0px.

Contenitore appiccicoso: è l'elemento HTML che avvolge l'elemento appiccicoso. Questa è l'area massima in cui l'oggetto appiccicoso può galleggiare.

Quando definisci un elemento con posizione: appiccicoso, definisci automaticamente l'elemento genitore come contenitore appiccicoso!


1

Il vero comportamento di un elemento appiccicoso è:

  • Innanzitutto è relativo per un po '
  • quindi viene risolto per un po '
  • infine, scompare dalla vista

Un elemento posizionato in modo appiccicoso viene trattato come relativamente posizionato fino a quando il suo blocco contenitore attraversa una soglia specificata (come l'impostazione di un valore superiore diverso da auto) all'interno della sua radice di flusso (o il contenitore in cui scorre), a quel punto viene trattato come "bloccato" "fino a incontrare il bordo opposto del suo blocco contenitore.

L'elemento viene posizionato in base al flusso normale del documento, quindi viene spostato rispetto al suo antenato a scorrimento più vicino e al blocco contenente (antenato a livello di blocco più vicino), inclusi gli elementi relativi alla tabella, in base ai valori di top, right, bottom, e sinistra. L'offset non influisce sulla posizione di altri elementi.

Questo valore crea sempre un nuovo contesto di sovrapposizione. Si noti che un elemento appiccicoso "si attacca" al suo antenato più vicino che ha un "meccanismo di scorrimento" (creato quando l'overflow è nascosto, scroll, auto o overlay), anche se quell'antenato non è l'antenato a scorrimento più vicino.

Questo esempio ti aiuterà a capire:

code https://codepen.io/darylljann/pen/PpjwPM


0

se la correzione di danday74 non funziona, controlla che l'elemento genitore abbia un'altezza.

Nel mio caso ho avuto due bambini, uno galleggiante a sinistra e uno galleggiante a destra. Volevo che il galleggiante giusto diventasse appiccicoso, ma dovevo aggiungere un <div style="clear: both;"></div>alla fine del genitore, per dargli altezza.


Non sono sicuro del motivo per cui questo è stato declassato da qualcuno, ma questo è stato esattamente il mio caso: ho aggiunto float:leftall'elemento genitore (senza float la sua altezza era 0) e ha position:stickyfunzionato.
aexl

0

Ho usato una soluzione JS. Funziona con Firefox e Chrome. Eventuali problemi, fammi sapere.

html

<body>
  <header id="header">
    <h1>Extra-Long Page Heading That Wraps</h1>
    <nav id="nav">
      <ul>
        <li><a href="" title="">Home</a></li>
        <li><a href="" title="">Page 2</a></li>
        <li><a href="" title="">Page 3</a></li>
      </ul>
    </nav>
  </header>
  <main>
    <p><!-- ridiculously long content --></p>
  </main>
  <footer>
    <p>FOOTER CONTENT</p>
  </footer>
  <script src="navbar.js" type="text/javascript"></script>
</body>

css

nav a {
    background: #aaa;
    font-size: 1.2rem;
    text-decoration: none;
    padding: 10px;
}

nav a:hover {
    background: #bbb;
}

nav li {
    background: #aaa;
    padding: 10px 0;

}

nav ul  {
    background: #aaa;
    list-style-type: none;
    margin: 0;
    padding: 0;

}

@media (min-width: 768px) {

    nav ul {
        display: flex;
    }
}

js

function applyNavbarSticky() {
    let header = document.querySelector('body > header:first-child')
    let navbar = document.querySelector('nav')
    header.style.position = 'sticky'

    function setTop() {
        let headerHeight = header.clientHeight
        let navbarHeight = navbar.clientHeight
        let styleTop = navbarHeight - headerHeight

        header.style.top = `${styleTop}px`
    }

    setTop()

    window.onresize = function () {
        setTop()
    }
}

0

z-indexè anche molto importante. A volte funzionerà ma non lo vedrai. Prova a impostarlo su un numero molto alto solo per essere sicuro. Inoltre, non sempre metti, top: 0ma prova qualcosa di più alto nel caso in cui sia nascosto da qualche parte (sotto una barra degli strumenti).


0

Ecco cosa mi ha fatto inciampare ... il mio div appiccicoso era all'interno di un altro div in modo che il div del genitore avesse bisogno di un po 'di contenuto aggiuntivo DOPO il div appiccicoso, per rendere il div del genitore "abbastanza alto" perché il div appiccicoso "scivolasse" su altri contenuti come scorri verso il basso.

Quindi nel mio caso, subito dopo il div appiccicoso, ho dovuto aggiungere:

    %div{style:"height:600px;"} 
      &nbsp;

(La mia applicazione ha due div affiancati, con un'immagine "alta" a sinistra e un breve modulo di inserimento dati a destra e volevo che il modulo di inserimento dati fluttuasse accanto all'immagine mentre scorri verso il basso, quindi il modulo è sempre sullo schermo. Non funzionerebbe fino a quando non avrò aggiunto il "contenuto aggiuntivo" sopra indicato, quindi il div appiccicoso ha qualcosa da "scorrere"


-1

È VERO che overflowbisogna rimuoverlo o impostarlo initialper far position: stickyfunzionare l'elemento figlio. Ho usato Material Design nella mia app Angular e ho scoperto che alcuni componenti Material hanno cambiato il overflowvalore. La correzione per il mio scenario è

mat-sidenav-container, mat-sidenav-content {
  overflow: initial;
}
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.