ScrollIntoView () khiến toàn bộ trang di chuyển


109

Tôi đang sử dụng ScrollIntoView () để cuộn mục được đánh dấu trong danh sách sang chế độ xem. Khi tôi cuộn xuống ScrollIntoView (false) hoạt động hoàn hảo. Nhưng khi tôi cuộn lên trên, ScrollIntoView (true) đang làm cho toàn bộ trang di chuyển một chút mà tôi nghĩ là dự định. Có cách nào để tránh di chuyển toàn bộ trang khi sử dụng ScrollIntoView (true) không?

Đây là cấu trúc trang của tôi -

#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 đến từ lệnh gọi ajax. Sử dụng safari di động.

Cảm ơn vì sự giúp đỡ của bạn trước đó!


1
Bạn có thể cung cấp JSFiddle để chúng tôi có thể xem chính xác vấn đề là gì không?
Robert Koritnik

Câu trả lời:


115

Bạn có thể sử dụng scrollTopthay vì scrollIntoView():

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

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

Nếu có nhiều hơn một phần tử có thể cuộn mà bạn muốn cuộn, bạn sẽ cần thay đổi scrollToptừng phần tử riêng lẻ, dựa trênoffsetTop phần tử xen vào. Điều này sẽ cung cấp cho bạn khả năng kiểm soát chi tiết để tránh sự cố bạn đang gặp phải.

CHỈNH SỬA: offsetTop không nhất thiết phải liên quan đến phần tử mẹ - nó liên quan đến tổ tiên được định vị đầu tiên. Nếu phần tử mẹ không được định vị (tương đối, tuyệt đối hoặc cố định), bạn có thể cần thay đổi dòng thứ hai thành:

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

3
FYI, điều này chỉ hoạt động khi trang gốc ở đầu trang. Bạn có lẽ nên làm cho nótarget.parentNode.scrollTop = target.offsetTop - target.parentNode.offsetTop
Phil

2
offsetTop có liên quan đến nút cha được định vị gần nhất, vì vậy nếu nút cha có position: relative, thì bạn không nên trừ phần bù của nó. Nhưng bạn đúng cho hầu hết các trường hợp.
Brilliand

2
Đây là js fiddle: jsfiddle.net/LEqjm/258 cũng hiển thị hành vi không đúng ScrollIntoView.
Rafi

1
@Brilliand cảm ơn bạn đã có ý tưởng về position: relativetrên div Prent: nó thực sự giải quyết vấn đề
Alex Zhukovskiy

Nó đang hoạt động trên chrome nhưng nó cuộn nhiều hơn một chút trên IE, nó sẽ ẩn nội dung văn bản từ trên xuống. Mọi giải pháp @Phil, Cảm ơn trước
Soniya

120

Đã sửa nó bằng:

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

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


1
Cảm ơn điều này đã làm việc. Tôi không hiểu việc sử dụng khối và các giá trị của nó khi tôi đọc nó. Bây giờ nó đã giải quyết được một vấn đề, tôi biết nó đang làm gì
Pavan

3
"Gần nhất" có nghĩa là gì? CHỈNH SỬA: Đã tìm thấy câu trả lời ở đây: stackoverflow.com/a/48635751/628418
Sammi

Điều này đã giải quyết vấn đề của tôi. Tôi đã thấy điều này xảy ra trong ứng dụng web của chúng tôi một thời gian, nhưng thật khó để khóa repro cho nó. Sau khi thêm một tính năng mới, nó xuất hiện liên tục và tôi có thể theo dõi nó đến cuộc gọi này, nó bị thiếu thông số block : 'nearest'.
roskelld

Giá như họ xác định được ý nghĩa của các giá trị khối .... bắt đầu và gần nhất ... tất cả các thử nghiệm và lỗi của nó.
Bae

Đối với tôi, hoạt động với Chrome, nhưng không hoạt động với Edge.
Michael

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

hoặc bạn có thể sử dụngtop: el['offsetTop']
Junior Mayhé

Điều này làm việc tốt nhất cho tôi. Nhưng vẫn còn một chút lỗi trên firefox - đôi khi nó dừng một phần đối với phần tử. Tốt về cạnh và chrome.
Đánh dấu

9

Tôi cũng gặp sự cố này và đã dành nhiều giờ để giải quyết nó. Tôi hy vọng giải pháp của tôi vẫn có thể giúp một số người.

Bản sửa lỗi của tôi đã kết thúc là:

  • Đối với Chrome: thay đổi .scrollIntoView()thành.scrollIntoView({block: 'nearest'}) (cảm ơn @jfrohn).
  • Đối với Firefox: áp dụng overflow: -moz-hidden-unscrollable;trên phần tử vùng chứa thay đổi.
  • Không được thử nghiệm trong các trình duyệt khác.

8

Chơi xung quanh với scrollIntoViewIfNeeded()... đảm bảo rằng nó được hỗ trợ bởi trình duyệt.


1
Không biết đó là một điều. Có một polyfill
mpen

Trong tài liệu, nó đã đề cập ở đó rằng nó không phải là tiêu chuẩn nhưng nó hoạt động tốt. chúng ta có nên sử dụng nó không?
Shyam Kumar

8

Tôi đã thêm một cách để hiển thị hành vi kém hiệu quả của ScrollIntoView - http://jsfiddle.net/LEqjm/258/ [đó phải là một nhận xét nhưng tôi không có đủ danh tiếng]

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

7
Không phải là một câu hỏi jQuery.
seangates

6

plugin jQuery scrollintoview() tăng khả năng sử dụng

Thay vì triển khai DOM mặc định, bạn có thể sử dụng một plugin tạo hoạt ảnh chuyển động và không có bất kỳ tác dụng không mong muốn nào. Đây là cách đơn giản nhất để sử dụng nó với mặc định:

$("yourTargetLiSelector").scrollintoview();

Dù sao, hãy xem bài đăng trên blog này , nơi bạn có thể đọc tất cả các chi tiết và cuối cùng sẽ đưa bạn đến mã nguồn GitHub của plugin.

Plugin này tự động tìm kiếm phần tử tổ tiên có thể cuộn gần nhất và cuộn nó để phần tử đã chọn nằm bên trong cổng xem hiển thị của nó. Nếu phần tử đã có trong cổng xem thì dĩ nhiên nó không làm gì cả.


19
@Brilliand: Điều đó tất nhiên đúng, nhưng điều đó không có nghĩa là họ không sử dụng nó hoặc miễn cưỡng sử dụng nó. Tất cả những gì tôi đang làm là cung cấp một giải pháp thay thế. OP để quyết định xem đó có phải là con đường họ sẽ đi hay không. Có thể họ chưa bao giờ nghĩ đến việc sử dụng jQuery ngay từ đầu.
Robert Koritnik

Việc OP không đề cập cụ thể jQuery là hoàn toàn không liên quan: câu trả lời của @ RobertKoritnik đã phục vụ tôi một cách hoàn hảo.
Dave Land

1
Ngẫu nhiên, Bing đang hiển thị mẫu mã của bạn trong kết quả tìm kiếm cho "ngăn phần tử tổ tiên cuộn với scrollintoview". :-)
Dave Land

2

Sử dụng ý tưởng của Brilliant, đây là giải pháp chỉ cuộn (theo chiều dọc) nếu phần tử hiện KHÔNG hiển thị. Ý tưởng là lấy hộp giới hạn của khung nhìn và phần tử được hiển thị trong không gian tọa độ cửa sổ trình duyệt. Kiểm tra xem nó có hiển thị không và nếu không, hãy cuộn theo khoảng cách cần thiết để phần tử được hiển thị ở trên cùng hoặc dưới cùng của khung nhìn.

    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

Thêm thông tin để @Jescođăng.

  • Element.scrollIntoViewIfNeeded() non-standard WebKit methodcho các trình duyệt Chrome, Opera, Safari.
    Nếu phần tử đã nằm trong vùng hiển thị của cửa sổ trình duyệt, thì không có thao tác cuộn nào diễn ra .
  • Element.scrollIntoView() phương thức cuộn phần tử mà nó được gọi vào vùng hiển thị của cửa sổ trình duyệt.

Hãy thử mã dưới đây trong mozilla.org scrollIntoView()liên kết. Đăng để xác định Trình duyệt

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

trong ngữ cảnh của tôi, anh ấy sẽ đẩy thanh công cụ dính ra khỏi màn hình hoặc nhập vào bên cạnh một nút tuyệt đối.

sử dụng giải pháp gần nhất.

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

1

tôi đã gặp vấn đề tương tự, tôi đã sửa nó bằng cách xóa transform:translateYCSS tôi đã đặt trên footertrang.

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.