Javascript scrollIntoView () mittlere Ausrichtung?

76

Javascript .scrollIntoView(boolean)bietet nur zwei Ausrichtungsoptionen.

  1. oben
  2. Unterseite

Was ist, wenn ich die Ansicht so scrollen möchte? Ich möchte ein bestimmtes Element irgendwo in die Mitte der Seite bringen.

DHRUV BANSAL
quelle

Antworten:

46

Verwenden Sie window.scrollTo()dazu. Holen Sie sich den oberen Rand des Elements, zu dem Sie verschieben möchten, und subtrahieren Sie die Hälfte der Fensterhöhe.

Demo: http://jsfiddle.net/ThinkingStiff/MJ69d/

Element.prototype.documentOffsetTop = function () {
    return this.offsetTop + ( this.offsetParent ? this.offsetParent.documentOffsetTop() : 0 );
};

var top = document.getElementById( 'middle' ).documentOffsetTop() - ( window.innerHeight / 2 );
window.scrollTo( 0, top );
ThinkingStiff
quelle
2
Es ist ein bisschen ineffizient, die gesamte
Elternkette hochzulaufen
Ich mag das offsetTop - (container / 2). einfach, aber ich habe nicht daran gedacht.
user2954463
85

Versuche dies :

 document.getElementById('myID').scrollIntoView({
            behavior: 'auto',
            block: 'center',
            inline: 'center'
        });

Weitere Informationen und Optionen finden Sie hier: https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView

Hakuna
quelle
9
In Kombination mit der Polyfüllung ist dies die beste Antwort. npmjs.com/package/smoothscroll-polyfill
Ryanrain
5
Nur Chrome und Opera unterstützen Block und Inline vollständig, nicht einmal die Smoothscroll-Polyfüllung. Es ist die Lösung, die wir wollen, aber leider nicht die, die funktioniert.
Dube
Ich verwende die gleiche Lösung in meinem Projekt auf IE11, Firefox, Chrome und Safari mit Angular 5.
Hakuna
2
@ Sri7 Safari, IE und Edge verstehen die Objektoption von nicht scrollIntoViewund tun, was sie wollen. Auch bei neuesten Versionen; Ich habe es gerade noch einmal getestet.
Dube
Ich kann bestätigen, dass dies auf mobilen Safari ab heute nicht funktioniert. window.scrollBy funktioniert.
Fabian von Ellerts
71

Es ist möglich getBoundingClientRect(), alle Informationen zu erhalten, die Sie benötigen, um dies zu erreichen. Zum Beispiel könnten Sie so etwas tun:

const element = document.getElementById('middle');
const elementRect = element.getBoundingClientRect();
const absoluteElementTop = elementRect.top + window.pageYOffset;
const middle = absoluteElementTop - (window.innerHeight / 2);
window.scrollTo(0, middle);

Demo: http://jsfiddle.net/cxe73c22/

Diese Lösung ist effizienter als das Überqueren der übergeordneten Kette, wie in der akzeptierten Antwort, und beinhaltet keine Verschmutzung des globalen Bereichs durch Erweiterung des Prototyps (im Allgemeinen als schlechte Praxis in Javascript angesehen ).

Die getBoundingClientRect()Methode wird in allen modernen Browsern unterstützt.

Rohan Orton
quelle
Leider bricht dies mit absolut positionierten Elementen.
Dube
Können Sie Ihre Antwort so bearbeiten, dass sie enthält, wie es gemacht wird, wenn sich das Element in einem scrollbaren Container anstelle der Seite befindet? Ich habe versucht: jsfiddle.net/qwxvts4u/1
JBis
Gelöst mit Hilfe von @KevinB jsfiddle.net/5ce062tn
JBis
8

Sie können dies in zwei Schritten tun:

myElement.scrollIntoView(true);
var viewportH = Math.max(document.documentElement.clientHeight, window.innerHeight || 0);
window.scrollBy(0, -viewportH/2); // Adjust scrolling with a negative value here

Sie können die Höhe des Elements hinzufügen, wenn Sie es global und nicht oben zentrieren möchten:

myElement.scrollIntoView(true);
var viewportH = Math.max(document.documentElement.clientHeight, window.innerHeight || 0);
window.scrollBy(0, (myElement.getBoundingClientRect().height-viewportH)/2);
fred727
quelle
2
Dies ist die beste Antwort für das Jahr 2018. Verwenden Sie zuerst die normale Option "scrollIntoView", da die Option "center" in Firefox 36 bis 58 fehlerhaft ist und die Optionen vom IE nicht unterstützt werden. Weitere Informationen finden Sie unter developer.mozilla.org/en-US/docs / Web / API / Element /… . Anschließend können Sie den Bildlauf zentrieren, indem Sie die Hälfte des Ansichtsfensters berechnen und den Bildlauf dorthin verschieben.
Crisc82
3

Mit JQuery verwende ich Folgendes:

function scrollToMiddle(id) {

    var elem_position = $(id).offset().top;
    var window_height = $(window).height();
    var y = elem_position - window_height/2;

    window.scrollTo(0,y);

}

Beispiel:

<div id="elemento1">Contenido</div>

<script>
    scrollToMiddle("#elemento1");
</script>
SergiP
quelle
3
document.getElementById("id").scrollIntoView({block: "center"});
Gregory R.
quelle
2

Verbesserung der Antwort @Rohan Ortonauf vertikale und horizontale Schriftrollen.

Die Methode Element.getBoundingClientRect () gibt die Größe eines Elements und seine Position relativ zum Ansichtsfenster zurück.

var ele = $x("//a[.='Ask Question']");
console.log( ele );

scrollIntoView( ele[0] );

function scrollIntoView( element ) {
    var innerHeight_Half = (window.innerHeight >> 1); // Int value
                        // = (window.innerHeight / 2); // Float value
    console.log('innerHeight_Half : '+ innerHeight_Half);

    var elementRect = element.getBoundingClientRect();

    window.scrollBy( (elementRect.left >> 1), elementRect.top - innerHeight_Half);
}

Verwenden Sie die Bitwise operatorRechtsverschiebung, um den int-Wert nach dem Teilen zu erhalten.

console.log( 25 / 2 ); // 12.5
console.log( 25 >> 1 ); // 12
Yash
quelle
2

Keine der Lösungen auf dieser Seite funktioniert, wenn ein anderer Container als das Fenster / Dokument gescrollt wird. Der getBoundingClientRectAnsatz schlägt mit absolut positionierten Elementen fehl.

In diesem Fall müssen wir zuerst das scrollbare übergeordnete Element bestimmen und es anstelle des Fensters scrollen. Hier ist eine Lösung, die in allen aktuellen Browserversionen funktioniert und sogar mit IE8 und Freunden funktionieren sollte. Der Trick besteht darin, das Element an den oberen Rand des Containers zu scrollen, damit wir genau wissen, wo es sich befindet, und dann die Hälfte der Bildschirmhöhe abzuziehen.

function getScrollParent(element, includeHidden, documentObj) {
    let style = getComputedStyle(element);
    const excludeStaticParent = style.position === 'absolute';
    const overflowRegex = includeHidden ? /(auto|scroll|hidden)/ : /(auto|scroll)/;

    if (style.position === 'fixed') {
        return documentObj.body;
    }
    let parent = element.parentElement;
    while (parent) {
        style = getComputedStyle(parent);
        if (excludeStaticParent && style.position === 'static') {
            continue;
        }
        if (overflowRegex.test(style.overflow + style.overflowY + style.overflowX)) {
            return parent;
        }
        parent = parent.parentElement;
    }

    return documentObj.body;
}

function scrollIntoViewCentered(element, windowObj = window, documentObj = document) {
    const parentElement = getScrollParent(element, false, documentObj);
    const viewportHeight = windowObj.innerHeight || 0;

    element.scrollIntoView(true);
    parentElement.scrollTop = parentElement.scrollTop - viewportHeight / 2;

    // some browsers (like FireFox) sometimes bounce back after scrolling
    // re-apply before the user notices.
    window.setTimeout(() => {
        element.scrollIntoView(true);
        parentElement.scrollTop = parentElement.scrollTop - viewportHeight / 2;
    }, 0);
}
dube
quelle
1

Das Scrollen in die Mitte eines Elements funktioniert gut, wenn das übergeordnete Element das CSS hat: overflow: scroll;

Wenn es sich um eine vertikale Liste handelt, können Sie diese verwenden document.getElementById("id").scrollIntoView({block: "center"});und das ausgewählte Element in die vertikale Mitte des übergeordneten Elements scrollen.

Ein Hoch auf Gregory R. und Hakuna für ihre guten Antworten.

Weiterführende Literatur:

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

https://developer.mozilla.org/en-US/docs/Web/CSS/overflow

Matt Wyndham
quelle