---
url: 'https://simonerescio.it/2017/03/chrome-cambia-centro-di-gravita-il-riferimento-non-e-document-ma-viewport'
title: 'Chrome cambia centro di gravità, il riferimento non è più il document ma il viewport'
author:
  name: Simone Rescio
  url: 'https://simonerescio.it/chi-sono/'
date: '2017-03-01T00:13:58+01:00'
modified: '2026-04-25T00:54:42+02:00'
type: post
summary: 'Da Chrome 56 il browser gestisce nativamente i cambiamenti di contenuto sopra il viewport, aggiornando la posizione di scroll in modo autonomo. Scopri come rilevare questo comportamento e adattare il tuo JavaScript.'
categories:
  - JavaScript
tags:
  - Chrome
  - cross browser
  - javascript
  - usabilità
  - viewport
image: 'https://simonerescio.it/wp-content/uploads/2017/02/chrome-above-the-fold-scroll-fix.png'
published: true
---

# Chrome cambia centro di gravità, il riferimento non è più il document ma il viewport

[![sistema cartesiano](https://simonerescio.it/wp-content/uploads/2017/02/xy-150x150.png)](https://simonerescio.it/2017/03/chrome-cambia-centro-di-gravita-il-riferimento-non-e-document-ma-viewport/xy)Ogni sistema ha bisogno di coordinate e regole di riferimento, in termini bidimensionali abbiamo per quello *cartesiano* un punto di origine partendo dal quale gli elementi crescono positivamente verso destra e verso l’alto, se si rimuovono unità in altezza ci si sposta verso il basso.[  

](https://simonerescio.it/2017/03/chrome-cambia-centro-di-gravita-il-riferimento-non-e-document-ma-viewport/tetris_scoring)

![Tetris: eliminazione della riga e caduta dei blocchi](https://simonerescio.it/wp-content/uploads/2017/02/tetris_scoring.gif)Prendiamo per esempio il famoso puzzle game [tetris](https://it.wikipedia.org/wiki/Tetris), man mano che i blocchi si accumulano, quando una riga viene completata e si totalizza un punteggio la suddetta riga venendo cancellata causa uno spostamento degli elementi soprastanti verso il basso, diciamo che il suo *sistema di gravità* è rivolto verso il basso, cosa accade invece in una pagina web nel browser?

- [1. La gravità nel browser è verso l’alto](#la-gravita-nel-browser-e-verso-l8217alto)
- [2. Aggiustare la posizione di scroll con il delta dell’altezza della pagina](#aggiustare-la-posizione-di-scroll-con-il-delta-dell8217altezza-della-pagina)
- [3. Chrome gestisce nativamente i cambiamenti sopra il viewport](#chromegestisce-nativamente-i-cambiamenti-sopra-il-viewport)

## La gravità nel browser è verso l’alto

![Animazione: spostamento verso l](https://simonerescio.it/wp-content/uploads/2017/02/standard-move-up.gif)Il punto zero di riferimento nel browser è l’angolo in alto a sinistra da cui inizia a svilupparsi la pagina verso il basso, da ciò consegue che se si scorre un *documento*, anzi di questi tempi è più contemporaneo dire una *webapp,* piuttosto corposa come una social timeline tipo *facebook* o *twitter*, ciò che viene rimosso o aggiunto al di sopra dell’area attualmente “*inquadrata*” causa un cambiamento improvviso dei contenuti visualizzati a video perché tutto trasla di conseguenza.

Non è il massimo dal punto di vista della UX, e anzi diventa particolarmente fastidioso in ambito mobile.

## Aggiustare la posizione di scroll con il delta dell’altezza della pagina

Se gli elementi che vengono modificati al di sopra dell’area visibile nel *viewport* non sono soggetti ad animazioni o transizioni sulla loro altezza, è possibile “compensare” questo spostamento visuale calcolando lo scarto di dimensione in più o in meno avvenuto sull’altezza complessiva della pagina e applicando tale differenza alla posizione di scroll:

```
function isInViewportOrAbove($element, className) {
    var domNode = $element.get(0),
        nodeCoordinates;

    // Node must be rendered on page to get its coordinates
    if (!$element.is(":visible")) {
        $element.removeClass(className);
        nodeCoordinates = domNode.getBoundingClientRect();
        $element.addClass(className);
    } else {
        nodeCoordinates = domNode.getBoundingClientRect();
    }

    return nodeCoordinates.top < $(window).height();
}

function compensateScrollDifference(previousDocumentHeight) {
    var currentDocumentHeight  = $(document).height(),
        documentHeightDelta    = previousDocumentHeight - currentDocumentHeight,
        currentScrollPosition  = $(document).scrollTop(),
        newScrollPosition      = currentScrollPosition - documentHeightDelta;

    $('html, body').scrollTop(newScrollPosition);
}

function toggleVisibilityWithScrollAdjustment($element, className) {
    var previousDocumentHeight = $(document).height();

    $element.toggleClass(className);

    if (isInViewportOrAbove($element, className)) {
        compensateScrollDifference(previousDocumentHeight);
    }
}
```

## Chrome gestisce nativamente i cambiamenti sopra il viewport

![Chrome: correzione automatica dello scroll per modifiche sopra il viewport](https://simonerescio.it/wp-content/uploads/2017/02/chrome-scroll-fix.gif)Grazie al fatto di aver corredato la funzionalità di cui sopra di diversi unit tests Jasmine, ho constatato che tale feature ha iniziato a malfunzionare in Chrome a partire dall’8 Febbraio, ovvero in concomitanza con l’aggiornamento **56**.

Il test in questione prevede che avendo una pagina alta 3000px con la posizione di scroll impostata a 1800px, rimuovendo un elemento superiore di altezza 100px con la suddetta funzione la posizione della pagina sarebbe diventata 1700px, su Chrome la posizione riportata era diventata 1600px come se fosse applicata 2 volte.

Mettendo un *breakpoint* in concomitanza al toggle della classe e precedente la chiamata per compensare lo scroll si nota che laddove gli altri browser subito dopo aver effettuato il cambio di visibilità mantengono inalterata la scroll position che noi stiamo per andare a modificare,

			
				[![Altri browser: posizione di scroll invariata subito dopo il toggle della classe](https://simonerescio.it/wp-content/uploads/2017/02/Schermata-2017-02-26-alle-15.47.40-300x75.png)](https://simonerescio.it/schermata-2017-02-26-alle-15-47-40)
			
				*
				safari (webkit) prima di effettuare il toggle
				*

			
				[![Altri browser: posizione di scroll stabile dopo la modifica della visibilità](https://simonerescio.it/wp-content/uploads/2017/02/Schermata-2017-02-26-alle-15.48.31-300x75.png)](https://simonerescio.it/schermata-2017-02-26-alle-15-48-31)
			
				*
				safari (webkit) dopo il toggle ha mantenuto inalterato $.scrollTop()
				*

		

Chrome invece subito dopo il toggle ha già corretto la posizione di scroll per conto suo per cui l’applicazione della nostra funzione risulterebbe dannosa.

			
				[![Chrome: scroll position già corretta autonomamente dopo il toggle](https://simonerescio.it/wp-content/uploads/2017/02/Schermata-2017-02-26-alle-15.30.05-300x58.png)](https://simonerescio.it/schermata-2017-02-26-alle-15-30-05)
			
				*
				chrome v56 (blink) prima di eseguire il toggle
				*

			
				[![Chrome: compensazione automatica dello scroll sopra il fold](https://simonerescio.it/wp-content/uploads/2017/02/Schermata-2017-02-26-alle-15.30.31-300x58.png)](https://simonerescio.it/schermata-2017-02-26-alle-15-30-31)
			
				*
				chrome v56 (blink) dopo il toggle ha già cambiato il valore $.scrollTop()
				*

		

Dunque bisogna controllare se il browser ha già operato dei cambiamenti sulla posizione di scroll per compensare dei cambiati avvenuti nella pagina, per decidere se intervenire o meno:

```
function toggleVisibilityWithScrollAdjustment($element, className) {
    var previousDocumentHeight = $(document).height(),
        preToggleScrollPosition = $(document).scrollTop(),
        postToggleScrollPosition,
        isScrollPositionUnchanged;

    $element.toggleClass(className);

    postToggleScrollPosition  = $(document).scrollTop();
    isScrollPositionUnchanged = preToggleScrollPosition === postToggleScrollPosition;

    if (isScrollPositionUnchanged && isInViewportOrAbove($element, className)) {
        compensateScrollDifference(previousDocumentHeight);
    }
}
```

Il meccanismo nativo di Chrome è particolarmente avanzato perché funziona anche per elementi animati, basta selezionare per esempio un immagine nel tag inspector e scorrere verso il basso per farla sparire in alto sopra il viewport, e modificando in qualunque modo la sua altezza non si noteranno cambiamenti nel viewport corrente.

Questo è solo un promemoria del fatto che i problemi *cross browser* sul front end sono ben lontani dall’estinzione.

 [](https://mastodon.social/share?text=http%3A%2F%2Fsresc.io%2FtLg&title=Chrome%20cambia%20centro%20di%20gravit%C3%A0%2C%20il%20riferimento%20non%20%C3%A8%20pi%C3%B9%20il%20document%20ma%20il%20viewport)[](https://www.linkedin.com/sharing/share-offsite/?url=http%3A%2F%2Fsresc.io%2FtLg)[](https://simonerescio.it/2017/03/chrome-cambia-centro-di-gravita-il-riferimento-non-e-document-ma-viewport)[](https://reddit.com/submit?url=http%3A%2F%2Fsresc.io%2FtLg&title=Chrome%20cambia%20centro%20di%20gravit%C3%A0%2C%20il%20riferimento%20non%20%C3%A8%20pi%C3%B9%20il%20document%20ma%20il%20viewport)[](https://api.whatsapp.com/send?text=Chrome%20cambia%20centro%20di%20gravit%C3%A0%2C%20il%20riferimento%20non%20%C3%A8%20pi%C3%B9%20il%20document%20ma%20il%20viewport http%3A%2F%2Fsresc.io%2FtLg)[](https://bsky.app/intent/compose?text=Chrome%20cambia%20centro%20di%20gravit%C3%A0%2C%20il%20riferimento%20non%20%C3%A8%20pi%C3%B9%20il%20document%20ma%20il%20viewport%20http%3A%2F%2Fsresc.io%2FtLg)[](https://telegram.me/share/url?url=http%3A%2F%2Fsresc.io%2FtLg&text=Chrome%20cambia%20centro%20di%20gravit%C3%A0%2C%20il%20riferimento%20non%20%C3%A8%20pi%C3%B9%20il%20document%20ma%20il%20viewport)[](https://www.facebook.com/sharer/sharer.php?u=http%3A%2F%2Fsresc.io%2FtLg)

