ScrollIntoView () che causa lo spostamento dell'intera pagina


110

Sto usando ScrollIntoView () per far scorrere l'elemento evidenziato in un elenco in visualizzazione. Quando scorro verso il basso ScrollIntoView (false) funziona perfettamente. Ma quando scorro verso l'alto, ScrollIntoView (true) fa sì che l'intera pagina si muova un po ', cosa che penso sia intesa. C'è un modo per evitare lo spostamento dell'intera pagina quando si utilizza ScrollIntoView (true)?

Ecco la struttura della mia pagina -

#listOfDivs {
  position:fixed;
  top:100px;
  width: 300px;
  height: 300px;
  overflow-y: scroll;
}

<div="container">
    <div="content"> 
         <div id="listOfDivs"> 
             <div id="item1"> </div>
             <div id="item2"> </div>
             <div id="itemn"> </div>
         </div>
    </div>
</div>

listOfDivs proviene da ajax call. Utilizzo di mobile safari.

Grazie per il vostro aiuto in anticipo!


1
Puoi fornire un JSFiddle in modo che possiamo vedere esattamente qual è il problema?
Robert Koritnik

Risposte:


115

Potresti usare al scrollTopposto di scrollIntoView():

var target = document.getElementById("target");
target.parentNode.scrollTop = target.offsetTop;

jsFiddle: http://jsfiddle.net/LEqjm/

Se c'è più di un elemento scorrevole che vuoi scorrere, dovrai cambiare il scrollTopdi ognuno individualmente, in base alla offsetTops degli elementi intermedi. Questo dovrebbe darti il ​​controllo dettagliato per evitare il problema che stai riscontrando.

EDIT: offsetTop non è necessariamente relativo all'elemento genitore, è relativo al primo antenato posizionato. Se l'elemento genitore non è posizionato (relativo, assoluto o fisso), potrebbe essere necessario modificare la seconda riga in:

target.parentNode.scrollTop = target.offsetTop - target.parentNode.offsetTop;

3
Cordiali saluti, funziona solo quando il genitore è nella parte superiore della pagina. Probabilmente dovresti farcelatarget.parentNode.scrollTop = target.offsetTop - target.parentNode.offsetTop
Phil

2
offsetTop è relativo al genitore posizionato più vicino, quindi se il nodo genitore lo ha position: relative, non dovresti sottrarre il suo offset. Ma hai ragione per la maggior parte dei casi.
Brilliand

2
Ecco un js fiddle: jsfiddle.net/LEqjm/258 che mostra anche il comportamento improprio di ScrollIntoView.
Rafi

1
@Brilliand grazie per l'idea position: relativesu prent div: risolve davvero il problema
Alex Zhukovskiy

Funziona su Chrome ma scorre un po 'di più su IE, che nasconde il contenuto del testo dall'alto. Qualsiasi soluzione @Phil, grazie in anticipo
Soniya

121

Risolto con:

element.scrollIntoView({ behavior: 'smooth', block: 'nearest', inline: 'start' })

vedere: https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView


1
Grazie, questo ha funzionato. Non sono riuscito a capire l'uso del blocco e dei suoi valori quando l'ho letto. Ora che ha risolto un problema so cosa sta facendo
Pavan

3
Cosa significa "più vicino"? EDIT: Ho trovato una risposta qui: stackoverflow.com/a/48635751/628418
Sammi

Questo ha risolto il mio problema. Lo vedo accadere nella nostra app Web da un po 'di tempo, ma è stato difficile bloccare la riproduzione per questo. Dopo aver aggiunto una nuova funzionalità si verificava ogni volta e sono stato in grado di risalire a questa chiamata, a cui mancava il block : 'nearest'parametro.
roskelld

Se solo definissero cosa significano i valori del blocco ... inizio e il più vicino ... è tutto per tentativi ed errori.
Bae

Funziona con Chrome, ma non con Edge per me.
Michael

13
var el = document.querySelector("yourElement");
window.scroll({top: el.offsetTop, behavior: 'smooth'});

oppure puoi usaretop: el['offsetTop']
Junior Mayhé

Questo funziona al meglio per me. Ma ancora un po 'di bug su Firefox - a volte si ferma a metà strada verso l'elemento. Belle sul bordo e cromate.
Contrassegna il

9

Anch'io ho avuto questo problema e ho passato molte ore a cercare di affrontarlo. Spero che la mia risoluzione possa ancora aiutare alcune persone.

La mia soluzione è finita per essere:

  • Per Chrome: passaggio .scrollIntoView()a .scrollIntoView({block: 'nearest'})(grazie a @jfrohn).
  • Per Firefox: applicare overflow: -moz-hidden-unscrollable;sull'elemento contenitore che si sposta.
  • Non testato in altri browser.

8

Gioca con scrollIntoViewIfNeeded()... assicurati che sia supportato dal browser.


1
Non sapevo che fosse una cosa. C'è un polyfill
mpen

Nel documento, è menzionato che non è standard ma funziona bene. dovremmo usarlo?
Shyam Kumar

8

Ho aggiunto un modo per visualizzare il comportamento imporper di ScrollIntoView - http://jsfiddle.net/LEqjm/258/ [dovrebbe essere un commento ma non ho abbastanza reputazione]

$("ul").click(function() {
    var target = document.getElementById("target");
if ($('#scrollTop').attr('checked')) {
    target.parentNode.scrollTop = target.offsetTop;    
} else {
        target.scrollIntoView(!0);
}
});

7
Non è una domanda su jQuery.
seangates

6

Il plugin jQuery scrollintoview()aumenta l'usabilità

Invece dell'implementazione DOM predefinita, puoi utilizzare un plug-in che anima il movimento e non ha effetti indesiderati. Ecco il modo più semplice per usarlo con i valori predefiniti:

$("yourTargetLiSelector").scrollintoview();

In ogni caso, vai a questo post del blog dove puoi leggere tutti i dettagli e alla fine ti porterà al codice sorgente GitHub del plugin.

Questo plugin cerca automaticamente l'elemento antenato scorrevole più vicino e lo fa scorrere in modo che l'elemento selezionato si trovi all'interno della sua porta di visualizzazione visibile. Se l'elemento è già nella porta di visualizzazione, ovviamente non fa nulla.


19
@Brilliand: Questo è ovviamente vero, ma ciò non significa che non lo stiano usando o che siano riluttanti a usarlo. Tutto quello che sto facendo è fornire un'alternativa. È su OP per decidere se questo è un percorso che avrebbero intrapreso o meno. Forse non hanno mai preso in considerazione l'utilizzo di jQuery in primo luogo.
Robert Koritnik

Quell'OP non ha menzionato specificamente jQuery è del tutto irrilevante: la risposta di @ RobertKoritnik mi è servita perfettamente.
Dave Land

1
Per inciso, Bing mostra il tuo esempio di codice nei risultati di ricerca per "mantieni l'elemento antenato dallo scorrimento con scrollintoview". :-)
Dave Land

2

Utilizzando l'idea di Brilliant, ecco una soluzione che scorre solo (verticalmente) se l'elemento NON è attualmente visibile. L'idea è di ottenere il riquadro di delimitazione della finestra e l'elemento da visualizzare nello spazio delle coordinate della finestra del browser. Controlla se è visibile e, in caso contrario, scorri per la distanza richiesta in modo che l'elemento sia mostrato nella parte superiore o inferiore della finestra.

    function ensure_visible(element_id)
    {
        // adjust these two to match your HTML hierarchy
        var element_to_show  = document.getElementById(element_id);
        var scrolling_parent = element_to_show.parentElement;

        var top = parseInt(scrolling_parent.getBoundingClientRect().top);
        var bot = parseInt(scrolling_parent.getBoundingClientRect().bottom);

        var now_top = parseInt(element_to_show.getBoundingClientRect().top);
        var now_bot = parseInt(element_to_show.getBoundingClientRect().bottom);

        // console.log("Element: "+now_top+";"+(now_bot)+" Viewport:"+top+";"+(bot) );

        var scroll_by = 0;
        if(now_top < top)
            scroll_by = -(top - now_top);
        else if(now_bot > bot)
            scroll_by = now_bot - bot;
        if(scroll_by != 0)
        {
            scrolling_parent.scrollTop += scroll_by; // tr.offsetTop;
        }
    }

2

Aggiunta di ulteriori informazioni al @Jescopost.

  • Element.scrollIntoViewIfNeeded() non-standard WebKit methodper browser Chrome, Opera, Safari.
    Se l'elemento si trova già nell'area visibile della finestra del browser, non viene eseguito lo scorrimento .
  • Element.scrollIntoView() il metodo fa scorrere l'elemento su cui è chiamato nell'area visibile della finestra del browser.

Prova il codice seguente nel mozilla.org scrollIntoView()link. Pubblica per identificare il browser

var xpath = '//*[@id="Notes"]';
ScrollToElement(xpath);

function ScrollToElement(xpath) {
    var ele = $x(xpath)[0];
    console.log( ele );

    var isChrome = !!window.chrome && (!!window.chrome.webstore || !!window.chrome.runtime);
    if (isChrome) { // Chrome
        ele.scrollIntoViewIfNeeded();
    } else {
        var inlineCenter = { behavior: 'smooth', block: 'center', inline: 'start' };
        ele.scrollIntoView(inlineCenter);
    }
}

2

nel mio contesto, spingerebbe la barra degli strumenti appiccicosa fuori dallo schermo o entrerebbe accanto a un pulsante favoloso con assoluto.

utilizzando il più vicino risolto.

const element = this.element.nativeElement;
const table = element.querySelector('.table-container');
table.scrollIntoView({
  behavior: 'smooth', block: 'nearest'
});

1

ho avuto lo stesso problema, l'ho risolto rimuovendo il transform:translateYCSS che ho inserito nella footerpagina.

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.