ScrollIntoView () tüm sayfanın hareket etmesine neden olur


110

Listedeki vurgulanan öğeyi görünüme kaydırmak için ScrollIntoView () kullanıyorum. Aşağı kaydırdığımda ScrollIntoView (false) mükemmel çalışıyor. Ancak yukarı kaydırdığımda, ScrollIntoView (true) tüm sayfanın amaçlandığını düşündüğüm biraz hareket etmesine neden oluyor. ScrollIntoView (true) kullanırken tüm sayfanın hareket etmesini önlemenin bir yolu var mı?

İşte sayfamın yapısı -

#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 ajax çağrısından geliyor. Mobil safariyi kullanma.

Yardımınız için şimdiden teşekkür ederiz!


1
Sorunun tam olarak ne olduğunu görebilmemiz için bir JSFiddle sağlayabilir misiniz?
Robert Koritnik

Yanıtlar:


120

Bunun scrollTopyerine kullanabilirsiniz scrollIntoView():

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

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

Kaydırmak istediğiniz birden fazla kaydırılabilir öğe varsa , araya giren öğelerin 'lerine scrollTopgöre her birini ayrı ayrı değiştirmeniz gerekir offsetTop. Bu, yaşadığınız sorunu önlemek için size en ince ayrıntısına kadar kontrol sağlamalıdır.

DÜZENLEME: offsetTop mutlaka ana öğeye bağlı değildir - ilk konumlandırılmış üst öğeye bağlıdır. Üst öğe konumlandırılmamışsa (göreceli, mutlak veya sabit), ikinci satırı şu şekilde değiştirmeniz gerekebilir:

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

4
Bilginize, bu yalnızca üst sayfa sayfanın en üstünde olduğunda çalışır. Muhtemelen yapmalısıntarget.parentNode.scrollTop = target.offsetTop - target.parentNode.offsetTop
Phil

2
offsetTop, en yakın konumlandırılmış ebeveyne görelidir, bu nedenle üst düğümde varsa position: relative, onun ofsetini çıkarmamalısınız. Ama çoğu durumda haklısın.
Brilliand

2
İşte bir js fiddle: jsfiddle.net/LEqjm/258 , ScrollIntoView uygunsuz davranışını da gösteriyor.
Rafi

1
@Brilliand position: relative, prent div hakkındaki fikriniz için teşekkür ederim : sorunu gerçekten çözdü
Alex Zhukovskiy

Chrome üzerinde çalışıyor ancak metin içeriğini yukarıdan gizleyen IE'de biraz daha fazla kaydırıyor. Herhangi bir çözüm @Phil, Şimdiden teşekkürler
Soniya

128

Şununla düzeltildi:

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

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


1
Teşekkürler bu işe yaradı. Okuduğumda bloğun kullanımını ve değerlerini anlayamadım. Artık bir sorunu çözdüğüne göre ne yaptığını biliyorum
Pavan

3
"En yakın" ne anlama geliyor? DÜZENLEME: Burada bir cevap
buldum

Bu benim sorunumu çözdü. Bir süredir web uygulamamızda bunun olduğunu görüyorum, ancak bunun için reproyu kilitlemek zordu. Yeni bir özellik ekledikten sonra her seferinde ortaya çıktı ve block : 'nearest'param eksik olan bu çağrıya kadar onu izleyebildim .
roskelld

Keşke blok değerlerinin ne anlama geldiğini tanımladılarsa .... başlangıç ​​ve en yakın ... hepsi deneme yanılma.
Bae

Chrome ile çalışıyor, ancak benim için Edge ile çalışmıyor.
Michael

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

veya kullanabilirsiniztop: el['offsetTop']
Junior Mayhé

Bu benim için en iyisi. Ama yine de firefox'ta biraz sorunlu - bazen öğenin bir kısmında durur. Kenar ve kromda iyi.
Mark

10

Ben de bu problemi yaşadım ve bununla başa çıkmak için saatler harcadım. Umarım kararım hala bazı insanlara yardımcı olabilir.

Düzeltmem şu oldu:

  • Chrome için: Değişen .scrollIntoView()için .scrollIntoView({block: 'nearest'})(teşekkürler @jfrohn kadar).
  • Firefox için: değişen overflow: -moz-hidden-unscrollable;kapsayıcı elemanına uygulayın .
  • Diğer tarayıcılarda test edilmemiştir.

9

Oynayın scrollIntoViewIfNeeded()... tarayıcı tarafından desteklendiğinden emin olun.


1
Bunun bir şey olduğunu bilmiyordum . Orada bir polyfill
mpen

Belgede, standart olmadığı ancak iyi çalıştığı belirtildi. onu kullanmalı mıyız?
Shyam Kumar

8

ScrollIntoView’un uygunsuz davranışını göstermenin bir yolunu ekledim - http://jsfiddle.net/LEqjm/258/ [bu bir yorum olmalı ama yeterli itibarım yok]

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

7
JQuery sorusu değil.
seangates

6

jQuery eklentisi scrollintoview()kullanılabilirliği artırır

Varsayılan DOM uygulaması yerine, hareketi canlandıran ve istenmeyen etkileri olmayan bir eklenti kullanabilirsiniz. Varsayılanlarla kullanmanın en basit yolu:

$("yourTargetLiSelector").scrollintoview();

Her neyse , tüm ayrıntıları okuyabileceğiniz ve sonunda sizi eklentinin GitHub kaynak koduna götürebileceğiniz bu blog gönderisine gidin .

Bu eklenti otomatik olarak en yakın kaydırılabilir üst öğe öğesini arar ve onu, seçilen öğe görünür görünüm portunun içinde olacak şekilde kaydırır. Öğe zaten görünüm portundaysa, elbette hiçbir şey yapmaz.


19
@Brilliand: Bu elbette doğru, ancak bu kullanmadıkları veya kullanmakta isteksiz oldukları anlamına gelmez. Tek yaptığım bir alternatif sunmak. Bunun izleyecekleri bir yol olup olmadığına karar vermek OP'ye bağlıdır. Belki ilk etapta jQuery kullanmayı hiç düşünmemişlerdir.
Robert Koritnik

OP'nin özellikle jQuery'den bahsetmemiş olması tamamen alakasız: @ RobertKoritnik'in cevabı bana mükemmel bir şekilde hizmet etti.
Dave Kara

1
Bu arada Bing, kod örneğinizi "üst öğenin kaydırma görünümü ile kaydırılmasını engelle" arama sonuçlarında gösteriyor. :-)
Dave Land

2

Brilliant'ın fikrini kullanarak, burada yalnızca (dikey olarak) öğe şu anda görünür DEĞİLSE kaydırılan bir çözüm var. Buradaki fikir, görüntü alanının sınırlayıcı kutusunu ve tarayıcı-pencere koordinat alanında görüntülenecek öğeyi elde etmektir. Görünür olup olmadığını kontrol edin ve değilse, öğenin görünüm penceresinin üstünde veya altında gösterilmesi için gerekli mesafe kadar kaydırı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

Göndermek için daha fazla bilgi @Jescoekleniyor.

  • Element.scrollIntoViewIfNeeded() non-standard WebKit methodChrome, Opera, Safari tarayıcıları için.
    Öğe zaten tarayıcı penceresinin görünen alanı içindeyse, o zaman kaydırma yapılmaz .
  • Element.scrollIntoView() yöntem, çağrıldığı öğeyi tarayıcı penceresinin görünür alanına kaydırır.

Aşağıdaki kodu mozilla.org scrollIntoView()bağlantıda deneyin . Tarayıcıyı tanımlamak için yayınlayın

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

benim bağlamımda, yapışkan araç çubuğunu ekrandan uzaklaştırır veya mutlak ile bir fab düğmesinin yanına girer.

en yakın kullanarak çözüldü.

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

1

Ben de aynı sorunu transform:translateYyaşadım footer, sayfanın üstüne yerleştirdiğim CSS'yi kaldırarak düzelttim .

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.