ScrollIntoView () menyebabkan seluruh halaman berpindah

110

Saya menggunakan ScrollIntoView () untuk menggulir item yang disorot dalam daftar ke tampilan. Ketika saya menggulir ke bawah ScrollIntoView (false) bekerja dengan sempurna. Tetapi ketika saya menggulir ke atas, ScrollIntoView (true) menyebabkan seluruh halaman bergerak sedikit yang menurut saya memang dimaksudkan. Apakah ada cara untuk menghindari pemindahan seluruh halaman saat menggunakan ScrollIntoView (true)?

Ini adalah struktur halaman saya -

#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 berasal dari panggilan ajax. Menggunakan safari seluler.

Terima kasih atas bantuan Anda sebelumnya!

Aku disini
sumber
1
Bisakah Anda memberikan JSFiddle sehingga kami dapat melihat dengan tepat apa masalahnya?
Robert Koritnik

Jawaban:

115

Anda bisa menggunakan scrollTopsebagai pengganti scrollIntoView():

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

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

Jika ada lebih dari satu elemen yang dapat digulir yang ingin Anda gulir, Anda harus mengubah scrollTopmasing-masing satu per satu, berdasarkan offsetTopelemen intervening. Ini akan memberi Anda kendali penuh untuk menghindari masalah yang Anda hadapi.

EDIT: offsetTop tidak selalu terkait dengan elemen induk - ini relatif terhadap leluhur yang diposisikan pertama. Jika elemen induk tidak diposisikan (relatif, absolut, atau tetap), Anda mungkin perlu mengubah baris kedua menjadi:

target.parentNode.scrollTop = target.offsetTop - target.parentNode.offsetTop;
Brilliand
sumber
3
FYI, ini hanya berfungsi ketika orang tua ada di bagian atas halaman. Anda mungkin harus membuatnyatarget.parentNode.scrollTop = target.offsetTop - target.parentNode.offsetTop
Phil
2
offsetTop adalah relatif terhadap posisi induk terdekat, jadi jika simpul induk memiliki position: relative, Anda tidak boleh mengurangi offsetnya. Tapi Anda benar untuk banyak kasus.
Brilliand
2
Berikut adalah biola js: jsfiddle.net/LEqjm/258 yang juga menunjukkan perilaku ScrollIntoView yang tidak tepat.
Rafi
1
@Brilliand terima kasih atas ide tentang position: relativediv prent: itu benar-benar memperbaiki masalah
Alex Zhukovskiy
Ini berfungsi di chrome tetapi menggulir sedikit lebih banyak di IE, yang menyembunyikan konten teks dari atas. Solusi apa pun @Phil, Terima kasih sebelumnya
Soniya
124

Perbaiki dengan:

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

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

jfrohn
sumber
1
Terima kasih ini berhasil. Saya gagal memahami penggunaan blok dan nilainya ketika saya membacanya. Sekarang setelah memecahkan masalah, saya tahu apa yang dilakukannya
Pavan
3
Apa artinya "terdekat"? EDIT: Menemukan jawabannya di sini: stackoverflow.com/a/48635751/628418
Sammi
Ini menyelesaikan masalah saya. Saya telah melihat ini terjadi di aplikasi web kami selama beberapa waktu, tetapi sulit untuk mengunci repro untuk itu. Setelah menambahkan fitur baru, hal itu terjadi setiap saat dan saya dapat melacaknya ke panggilan ini, yang block : 'nearest'parameternya tidak ada.
roskelld
Jika saja mereka mendefinisikan apa arti nilai blok .... mulai dan terdekat ... semua trial and error.
Bae
Berfungsi dengan Chrome, tetapi tidak dengan Edge untuk saya.
Michael
13
var el = document.querySelector("yourElement");
window.scroll({top: el.offsetTop, behavior: 'smooth'});
momen dipol
sumber
atau Anda dapat menggunakantop: el['offsetTop']
Junior Mayhé
Ini yang terbaik untuk saya. Tapi masih sedikit buggy di firefox - terkadang berhenti di tengah jalan menuju elemen. Halus di tepi dan krom.
Tandai
9

Saya mengalami masalah ini juga, dan menghabiskan waktu berjam-jam untuk mengatasinya. Saya berharap resolusi saya masih dapat membantu beberapa orang.

Perbaikan saya akhirnya menjadi:

  • Untuk Chrome: berubah .scrollIntoView()menjadi .scrollIntoView({block: 'nearest'})(terima kasih kepada @jfrohn).
  • Untuk Firefox: terapkan overflow: -moz-hidden-unscrollable;pada elemen penampung yang bergeser.
  • Tidak diuji di browser lain.
paddotk
sumber
8

Bermain-main dengan scrollIntoViewIfNeeded()... pastikan itu didukung oleh browser.

Jesco
sumber
1
Tidak tahu bahwa itu suatu hal. Ada polyfill
mpen
Dalam dokumen, disebutkan di sana bahwa itu tidak standar tetapi berfungsi dengan baik. haruskah kita menggunakannya?
Shyam Kumar
8

Saya telah menambahkan cara untuk menampilkan perilaku penting ScrollIntoView - http://jsfiddle.net/LEqjm/258/ [ini seharusnya menjadi komentar tetapi saya tidak memiliki cukup reputasi]

$("ul").click(function() {
    var target = document.getElementById("target");
if ($('#scrollTop').attr('checked')) {
    target.parentNode.scrollTop = target.offsetTop;    
} else {
        target.scrollIntoView(!0);
}
});
Michal Tsadok
sumber
7
Bukan pertanyaan jQuery.
seangates
6

Plugin jQuery scrollintoview()meningkatkan kegunaan

Alih-alih penerapan DOM default, Anda dapat menggunakan plugin yang menganimasikan gerakan dan tidak memiliki efek yang tidak diinginkan. Berikut cara paling sederhana untuk menggunakannya dengan default:

$("yourTargetLiSelector").scrollintoview();

Buka posting blog ini di mana Anda dapat membaca semua detailnya dan pada akhirnya akan membawa Anda ke kode sumber GitHub dari plugin tersebut.

Plugin ini secara otomatis mencari elemen leluhur terdekat yang dapat di-scroll dan menggulirnya sehingga elemen yang dipilih berada di dalam port tampilan yang terlihat. Jika elemen sudah ada di port tampilan, ia tentu saja tidak melakukan apa-apa.

Robert Koritnik
sumber
19
@Brilliand: Itu tentu saja benar, tetapi itu tidak berarti bahwa mereka tidak menggunakannya atau enggan menggunakannya. Yang saya lakukan hanyalah memberikan alternatif. Terserah OP untuk memutuskan apakah itu jalan yang akan mereka ambil atau tidak. Mungkin mereka tidak pernah mempertimbangkan untuk menggunakan jQuery sejak awal.
Robert Koritnik
OP itu tidak secara khusus menyebutkan jQuery sama sekali tidak relevan: Jawaban @RobertKoritnik sangat membantu saya.
Dave Land
1
Secara tidak sengaja, Bing menampilkan sampel kode Anda di hasil penelusuran untuk "menjaga elemen leluhur agar tidak bergulir dengan scrollintoview". :-)
Dave Land
2

Menggunakan ide Brilliant, berikut adalah solusi yang hanya (secara vertikal) menggulung jika elemen saat ini TIDAK terlihat. Idenya adalah untuk mendapatkan kotak pembatas viewport dan elemen yang akan ditampilkan di ruang koordinat jendela browser. Periksa apakah terlihat dan jika tidak, gulir sejauh yang diperlukan sehingga elemen ditampilkan di bagian atas atau bawah viewport.

    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;
        }
    }
KungPhoo
sumber
2

Menambahkan lebih banyak informasi untuk @Jescomemposting.

  • Element.scrollIntoViewIfNeeded() non-standard WebKit methoduntuk browser Chrome, Opera, Safari.
    Jika elemen sudah berada dalam area yang terlihat di jendela browser, maka tidak ada pengguliran yang terjadi .
  • Element.scrollIntoView() metode menggulung elemen yang dipanggil ke dalam area yang terlihat di jendela browser.

Coba kode di bawah ini di mozilla.org scrollIntoView()tautan. Posting untuk mengidentifikasi 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);
    }
}
Yash
sumber
2

dalam konteks saya, dia akan mendorong bilah alat lengket dari layar, atau masuk di sebelah tombol hebat dengan absolut.

menggunakan penyelesaian terdekat.

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

saya memiliki masalah yang sama, saya memperbaikinya dengan menghapus transform:translateYCSS yang saya tempatkan di footerhalaman.

yael kfir
sumber