Se hai mai impostato position: sticky su un menu laterale o su un indice e lo hai visto semplicemente… rifiutarsi di rimanere incollato, non sei il solo.

Perché CSS position: sticky smette di funzionare (e come l'overflow su html/body lo rompe)

In questo articolo ti mostrerò un caso reale in cui mi sono imbattuto, tra cui:

  • Il motivo reale per cui il posizionamento sticky fallisce
  • Come diagnosticarlo correttamente nei DevTools
  • Perché l’overflow su html e body era il colpevole e come risolverlo

con un’analisi passo dopo passo riproducibile.


Il malinteso comune su position: sticky

Potresti avere del codice CSS che sembra perfettamente corretto, così:

css
.category-toc {
  position: sticky;
  top: 100px;
}

E continuare a riscontrare gli stessi problemi:

  • position: sticky è impostato, ma non succede nulla
  • top è definito
  • Nessun overflow: hidden su alcun elemento genitore (o almeno così credi)

Se ancora non si attacca, ci sono buone probabilità che la dichiarazione in sé sia corretta, ma che qualcosa a livello strutturale la stia boicottando silenziosamente.


Cosa controllare per primo (diagnosi con i DevTools)

Apri i DevTools in Chrome (o Edge), vai nella scheda Console ed esegui:

js
const el = document.querySelector('.category-toc');

getComputedStyle(el).position
getComputedStyle(el).top
getComputedStyle(el).overflow

[!NOTE] Se è la prima volta che incolli qualcosa nella console, potresti dover digitare manualmente “allow pasting” prima che Chrome ti permetta di farlo.

Come appare un risultato corretto

txt
position: "sticky"
top: "100px"
overflow: "visible"

Se questi valori sembrano corretti, la dichiarazione sticky in sé non è il problema.

Se continua a non funzionare dopo averlo confermato, il sospettato successivo si trova altrove.

La causa principale più comune: overflow su html / body

Nel mio caso, il colpevole erano le impostazioni di overflow su html e body.

Il controllo della console ha rivelato qualcosa del genere:

js
{
  scrollingElement: 'html',
  htmlOverflow: 'hidden auto',
  bodyOverflow: 'auto'
}

Il che significava sostanzialmente:

  • html: overflow-x: hidden; overflow-y: auto
  • body: overflow: auto

In altre parole, erano attivi due contenitori di scorrimento separati contemporaneamente.

Perché l’overflow su html/body rompe lo sticky

position: sticky calcola la sua posizione rispetto a:

  • Ilantenitore con scorrimento più vicino, oppure
  • La viewport, se non ce n’è uno

Ma quando:

  • html è scorrevole
  • Anche body è scorrevole
  • E c’è un elemento wrapper sopra di essi

…il browser non riesce a determinare con affidabilità a quale contenitore debba essere ancorato lo sticky, e il risultato pratico è un elemento che sembra ignorare completamente il posizionamento sticky.

La soluzione: lascia che sia html a gestire lo scorrimento e riporta body al flusso normale

La soluzione più affidabile è questa:

css
html {
  overflow-x: hidden;
  overflow-y: auto;
}

body {
  overflow: visible;
}

Punti chiave

  • Centralizza lo scorrimento verticale solo su html
  • Non impostare overflow: auto su body
  • Va bene mantenere overflow-x: hidden per prevenire lo scorrimento orizzontale

Nel momento in cui questa modifica è stata applicata, l’elemento sticky che si era rifiutato di funzionare ha iniziato a farlo immediatamente.


Testarlo subito dal vivo nella console

Prima di toccare il tuo vero CSS, puoi testare questo comportamento temporaneamente nella console:

js
document.documentElement.style.overflowY = 'auto';
document.documentElement.style.overflowX = 'hidden';
document.body.style.overflow = 'visible';

Se lo sticky inizia a funzionare dopo aver eseguito questo comando, hai la conferma che l’overflow è la causa.

Attenzione a queste regressioni comuni

Il posizionamento sticky potrebbe rompersi di nuovo se in seguito nel tuo codice dovesse comparire uno dei seguenti elementi:

  • Implementazioni di modali che lasciano html { overflow: hidden } permanentemente attivo
  • Codice di layout che imposta body { overflow: auto } per motivi non correlati
  • Un wrapper height: 100vh combinato con un proprio controllo dell’overflow

Se hai bisogno di bloccare lo scorrimento mentre una modale è aperta, è più sicuro mantenere overflow: auto come stato predefinito e passare a hidden solo mentre la modale è attiva:

css
html {
  overflow-y: auto;
  overflow-x: hidden;
}

.modal-open html {
  overflow: hidden;
}

Riepilogo: cosa controllare quando lo sticky non si “incolla”

  • Non dare per scontato che sia tutto sicuro solo perché position e top appaiono corretti
  • Controlla overflow su html e body, non solo sul genitore immediato
  • Assicurati che ci sia un solo contenitore di scorrimento attivo nella pagina

Il più delle volte, i problemi di posizionamento sticky dipendono da dove sta effettivamente scorrendo la pagina piuttosto che da un errore nel modo in cui lo sticky è scritto.

Sperando che questo risparmi ad altri la stessa sessione di debug.