Javascript scrollIntoView () середнє вирівнювання?


77

Javascript .scrollIntoView(boolean)надає лише два варіанти вирівнювання.

  1. зверху
  2. знизу

Що робити, якщо я хочу прокрутити подання таким чином. Я хочу принести конкретний елемент кудись посередині сторінки?

Відповіді:


47

Використовуйте window.scrollTo()для цього. Отримати верх елемента, до якого ви хочете перейти, і відняти половину висоти вікна.

Демо: 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 );

2
Трохи неефективно ходити по всьому батьківському ланцюжку
deiga

мені подобається offsetTop - (container / 2). просто, але я про це не думав.
user2954463

88

спробуйте це :

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

зверніться сюди для отримання додаткової інформації та варіантів: https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView


9
у поєднанні з поліфілом це найкраща відповідь. npmjs.com/package/smoothscroll-polyfill
ryanrain

5
Тільки Chrome і Opera повністю підтримують блокування та вбудовування, навіть поліпсивна прокрутка не робить цього. Це рішення, яке ми хочемо, але, на жаль, не те, яке працює.
дуб

Я використовую те саме рішення у своєму проекті на IE11, Firefox, Chrome та Safari з Angular 5.
hakuna

2
@ Sri7 Safari, IE та Edge не розуміють варіант об'єкта scrollIntoViewі роблять все, що хочуть. Навіть на останніх версіях; Я просто перевірив це ще раз.
дуб

Я можу підтвердити, що на сьогодні це не працює в мобільному сафарі. window.scrollBy працює.
Фабіан фон Еллерц

71

Це можна використовувати, getBoundingClientRect()щоб отримати всю інформацію, необхідну для досягнення цього. Наприклад, ви можете зробити щось подібне:

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);

Демо: http://jsfiddle.net/cxe73c22/

Це рішення є більш ефективним, ніж підняття батьківського ланцюга, як у прийнятій відповіді, і не передбачає забруднення глобальної сфери шляхом розширення прототипу ( як правило, вважається поганою практикою в javascript ).

getBoundingClientRect()Метод підтримується в усі сучасному браузері.


На жаль, це розривається з абсолютно позиціонованими елементами.
дуб

Чи можете ви відредагувати свою відповідь, включивши, як це зробити, коли елемент знаходиться в прокручуваному контейнері замість сторінки? Я намагався: jsfiddle.net/qwxvts4u/1
JBis

Вирішено за допомогою @KevinB jsfiddle.net/5ce062tn
JBis

8

Ви можете зробити це у два етапи:

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

Ви можете додати висоту елемента, якщо хочете відцентрувати його глобально, а не центрувати його верх:

myElement.scrollIntoView(true);
var viewportH = Math.max(document.documentElement.clientHeight, window.innerHeight || 0);
window.scrollBy(0, (myElement.getBoundingClientRect().height-viewportH)/2);

2
це найкраща відповідь у 2018 році. спочатку використовуйте звичайний "scrollIntoView", оскільки параметр "center" у Firefox 36 до 58 порушений, а IE не підтримує параметри, див. цього розробника. mozilla.org/en-US/docs / Web / API / Element /… . тоді ви можете відцентрувати прокрутку, обчисливши половину області перегляду і перемістивши туди прокрутку.
crisc82

5
document.getElementById("id").scrollIntoView({block: "center"});

Мені це знадобилося для вертикально прокручуваної таблиці з фіксованим заголовком, і це працює для мене.
Атік Бакі

3

З JQuery я використовую це:

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);

}

Приклад:

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

<script>
    scrollToMiddle("#elemento1");
</script>

3

Прокрутка до середини елемента працює добре, якщо його батьківський елемент має css: overflow: scroll;

Якщо це вертикальний список, ви можете використовувати document.getElementById("id").scrollIntoView({block: "center"});його, і він прокрутить вибраний елемент до вертикальної середини батьківського елемента.

Вітаємо Грегорі Р. та Хакуну за хороші відповіді.

Подальше читання:

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

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


2

Покращення відповіді @Rohan Ortonна роботу для вертикальної та горизонтальної прокрутки.

Метод Element.getBoundingClientRect () повертає розмір елемента та його положення щодо області перегляду.

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);
}

Використання Bitwise operatorправого зсуву для отримання значення int після ділення.

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

2

Жодне з рішень на цій сторінці не працює, коли контейнер, крім вікна / документа, прокручується. getBoundingClientRectПідхід не з абсолютними позиціонувати елементами.

У цьому випадку нам потрібно спочатку визначити прокручуваний батько та прокрутити його замість вікна. Ось рішення, яке працює у всіх поточних версіях браузера і має працювати навіть з IE8 та друзями. Фокус полягає в тому, щоб прокрутити елемент до верху контейнера, щоб ми точно знали, де він знаходиться, а потім відняти половину висоти екрану.

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);
}

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.