Căn giữa Javascript scrollIntoView ()?


77

Javascript .scrollIntoView(boolean)chỉ cung cấp hai tùy chọn căn chỉnh.

  1. hàng đầu
  2. đáy

Điều gì sẽ xảy ra nếu tôi muốn cuộn chế độ xem như vậy. Tôi muốn đưa yếu tố cụ thể vào đâu đó ở giữa trang?

Câu trả lời:


47

Sử dụng window.scrollTo()cho việc này. Lấy phần trên cùng của phần tử bạn muốn di chuyển đến và trừ đi một nửa chiều cao cửa sổ.

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

2
Sẽ hơi kém hiệu quả khi đi lên toàn bộ chuỗi mẹ
deiga

tôi thích offsetTop - (container / 2). đơn giản, nhưng tôi không nghĩ ra.
user2954463.

88

thử cái này :

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

tham khảo tại đây để biết thêm thông tin và các tùy chọn: https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView


9
kết hợp với polyfill, đây là câu trả lời tốt nhất. npmjs.com/package/smoothscroll-polyfill
ryanrain

5
Chỉ có Chrome và Opera hỗ trợ đầy đủ khối và nội tuyến, ngay cả polyfill mượt mà cũng không hỗ trợ. Đó là giải pháp chúng tôi muốn, nhưng đáng buồn là không phải giải pháp nào hiệu quả.
dube

Tôi đang sử dụng cùng một giải pháp trong dự án của mình trên IE11, Firefox, Chrome và Safari với Angular 5.
hakuna

2
@ Sri7 Safari, IE và Edge không hiểu tùy chọn đối tượng scrollIntoViewvà làm bất cứ điều gì họ muốn. Ngay cả trên các phiên bản mới nhất; Tôi chỉ thử nghiệm nó một lần nữa.
dube

Tôi có thể xác nhận rằng điều này không hoạt động trên safari di động kể từ hôm nay. window.scrollBy hoạt động.
Fabian von Ellerts

71

Có thể sử dụng getBoundingClientRect()để lấy tất cả thông tin bạn cần để đạt được điều này. Ví dụ, bạn có thể làm điều gì đó như sau:

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

Bản giới thiệu: http://jsfiddle.net/cxe73c22/

Giải pháp này hiệu quả hơn so với việc lập chuỗi mẹ, như trong câu trả lời được chấp nhận và không liên quan đến việc gây ô nhiễm phạm vi toàn cầu bằng cách mở rộng nguyên mẫu ( thường được coi là hành vi xấu trong javascript ).

Các getBoundingClientRect()phương pháp được hỗ trợ trong tất cả các trình duyệt hiện đại.


Đáng buồn thay, điều này phá vỡ với các yếu tố định vị tuyệt đối.
dube

Bạn có thể chỉnh sửa câu trả lời của mình để bao gồm cách thực hiện khi phần tử nằm trong vùng chứa có thể cuộn thay vì trang không? Tôi đã thử: jsfiddle.net/qwxvts4u/1
JBis

Được giải quyết với sự trợ giúp của @KevinB jsfiddle.net/5ce062tn
JBis

8

Bạn có thể thực hiện theo hai bước:

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

Bạn có thể thêm chiều cao của phần tử nếu bạn muốn căn giữa nó toàn cục và không căn giữa phần trên:

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

2
đây là câu trả lời tốt nhất cho năm 2018. Trước tiên, hãy sử dụng "scrollIntoView" bình thường, vì tùy chọn "center" bị hỏng trong Firefox 36 đến 58 và các tùy chọn này không được IE hỗ trợ, hãy xem developer.mozilla.org/en-US/docs / Web / API / Phần tử /… . thì bạn có thể căn giữa cuộn bằng cách tính toán một nửa khung nhìn và di chuyển cuộn đến đó.
khủng hoảng 82,


3

Với JQuery, tôi sử dụng cái này:

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

}

Thí dụ:

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

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

3

Cuộn đến giữa phần tử hoạt động tốt nếu phần tử mẹ của nó có css: overflow: scroll;

Nếu đó là danh sách dọc, bạn có thể sử dụng document.getElementById("id").scrollIntoView({block: "center"}); và nó sẽ cuộn phần tử đã chọn của bạn đến giữa theo chiều dọc của phần tử mẹ.

Chúc mừng Gregory R. và Hakuna vì những câu trả lời hay của họ.

Đọc thêm:

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

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


2

Cải thiện câu trả lời @Rohan Ortonđể làm việc cho cuộn dọc và ngang.

Phương thức Element.getBoundsClientRect () trả về kích thước của một phần tử và vị trí của nó so với khung nhìn.

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

Sử dụng Bitwise operatordịch chuyển phải để nhận giá trị int sau khi chia.

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

2

Không có giải pháp nào trên trang này hoạt động khi một vùng chứa không phải cửa sổ / tài liệu được cuộn. Cách getBoundingClientRecttiếp cận không thành công với các yếu tố được định vị tuyệt đối.

Trong trường hợp đó, chúng ta cần xác định cha mẹ có thể cuộn trước và cuộn nó thay vì cửa sổ. Đây là một giải pháp hoạt động trên tất cả các phiên bản trình duyệt hiện tại và thậm chí sẽ hoạt động với IE8 và bạn bè. Bí quyết là cuộn phần tử lên đầu vùng chứa để chúng ta biết chính xác vị trí của nó, sau đó trừ đi một nửa chiều cao của màn hình.

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

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.