Wie scrolle ich zu einem Element innerhalb eines Div?

170

Ich habe einen Bildlauf divund möchte einen Link haben, wenn ich darauf klicke. Dadurch wird ein Bildlauf diverzwungen, um ein Element darin anzuzeigen. Ich habe sein JavasSript so geschrieben:

document.getElementById(chr).scrollIntoView(true);

Dadurch wird jedoch die gesamte Seite gescrollt, während die Seite divselbst gescrollt wird . Wie kann man das beheben?

Ich möchte es so sagen

MyContainerDiv.getElementById(chr).scrollIntoView(true);
Amr Elgarhy
quelle
Scrolltop gibt nicht immer einen verwendbaren Wert zurück. Ich neige dazu, ein SetTimeoutin der $(document).ready({})Funktion zu verwenden und focus()auf das Element zu setzen, zu dem Sie scrollen möchten. Funktioniert für mich
DerpyNerd

Antworten:

339

Sie müssen den oberen Versatz des Elements, in das Sie scrollen möchten, relativ zu seinem übergeordneten Element (dem scrollenden div-Container) abrufen:

var myElement = document.getElementById('element_within_div');
var topPos = myElement.offsetTop;

Die Variable topPos wird jetzt auf den Abstand zwischen dem oberen Rand des Bildlauf-Div und dem Element eingestellt, das sichtbar sein soll (in Pixel).

Jetzt weisen wir das div an, zu dieser Position zu scrollen, indem wir scrollTop:

document.getElementById('scrolling_div').scrollTop = topPos;

Wenn Sie das Prototyp-JS-Framework verwenden, gehen Sie wie folgt vor:

var posArray = $('element_within_div').positionedOffset();
$('scrolling_div').scrollTop = posArray[1];

Auch hier wird das div so gescrollt, dass sich das gewünschte Element genau oben befindet (oder, falls dies nicht möglich ist, so weit wie möglich nach unten gescrollt, damit es sichtbar ist).

Brian Barrett
quelle
9
Das war wirklich hilfreich! Wenn Sie den Bildlauf mehrmals einstellen möchten, müssen Sie ihn um Ihren aktuellen Bildlaufort versetzen. So habe ich es in jQuery gemacht: $ ('# scrolling_div'). ScrollTop ($ ('# scrolling_div'). ScrollTop () + $ ('# element_within_div'). Position (). Top);
Will
3
Beachten Sie, dass das Anfordern myElement.offsetTopeinen Reflow (Layout-Thrashing) auslöst, der einen Leistungsengpass darstellen kann
Kestutis
26
Denken Sie daran, das übergeordnete Bildlaufelement mit CSS festzulegen. position: relativeAndernfalls verbringen Sie viel Zeit mit dem Debuggen, wie ich es gerade getan habe.
Savedario
2
Ich musste die overflow-yEigenschaft scrollfür das übergeordnete Element ( scrolling_div) festlegen , sonst funktionierte es nicht. Der Standard-CSS-Wert für die overflowEigenschaft ist autound obwohl es auch manuelles Scrollen ermöglicht, würde der JS-Code nicht funktionieren (nicht einmal mit {psition: relative}..)
Evgenia Manolova
2
Funktioniert auch 2017 noch. Zusätzliche Informationen: .offsetTop gibt möglicherweise 0 zurück. Dann sollten Sie auf ein übergeordnetes Element verweisen und es erneut versuchen. Ich habe das für Tags h4dann divdann articleTag und nur articlefür mich gearbeitet.
Fenio
66

Sie müssten die Position des Elements in dem DIV finden, zu dem Sie einen Bildlauf durchführen möchten, und die Eigenschaft scrollTop festlegen.

divElem.scrollTop = 0;

Update :

Beispielcode zum Auf- oder Abbewegen

  function move_up() {
    document.getElementById('divElem').scrollTop += 10;
  }

  function move_down() {
    document.getElementById('divElem').scrollTop -= 10;
  }
Glennular
quelle
3
Ich möchte es Ansicht scrollen, um zu sehen, dass es nicht mit einem bestimmten Wert
scrollt
39

Methode 1 - Reibungsloses Scrollen zu einem Element innerhalb eines Elements

var box = document.querySelector('.box'),
    targetElm = document.querySelector('.boxChild'); // <-- Scroll to here within ".box"

document.querySelector('button').addEventListener('click', function(){
   scrollToElm( box, targetElm , 600 );   
});


/////////////

function scrollToElm(container, elm, duration){
  var pos = getRelativePos(elm);
  scrollTo( container, pos.top , 2);  // duration in seconds
}

function getRelativePos(elm){
  var pPos = elm.parentNode.getBoundingClientRect(), // parent pos
      cPos = elm.getBoundingClientRect(), // target pos
      pos = {};

  pos.top    = cPos.top    - pPos.top + elm.parentNode.scrollTop,
  pos.right  = cPos.right  - pPos.right,
  pos.bottom = cPos.bottom - pPos.bottom,
  pos.left   = cPos.left   - pPos.left;

  return pos;
}
    
function scrollTo(element, to, duration, onDone) {
    var start = element.scrollTop,
        change = to - start,
        startTime = performance.now(),
        val, now, elapsed, t;

    function animateScroll(){
        now = performance.now();
        elapsed = (now - startTime)/1000;
        t = (elapsed/duration);

        element.scrollTop = start + change * easeInOutQuad(t);

        if( t < 1 )
            window.requestAnimationFrame(animateScroll);
        else
            onDone && onDone();
    };

    animateScroll();
}

function easeInOutQuad(t){ return t<.5 ? 2*t*t : -1+(4-2*t)*t };
.box{ width:80%; border:2px dashed; height:180px; overflow:auto; }
.boxChild{ 
  margin:600px 0 300px; 
  width: 40px;
  height:40px;
  background:green;
}
<button>Scroll to element</button>
<div class='box'>
  <div class='boxChild'></div>
</div>

Methode 2 - Verwenden von Element.scrollIntoView :

Beachten Sie, dass die Browserunterstützung für diesen nicht besonders gut ist

var targetElm = document.querySelector('.boxChild'),  // reference to scroll target
    button = document.querySelector('button');        // button that triggers the scroll
  
// bind "click" event to a button 
button.addEventListener('click', function(){
   targetElm.scrollIntoView()
})
.box {
  width: 80%;
  border: 2px dashed;
  height: 180px;
  overflow: auto;
  scroll-behavior: smooth; /* <-- for smooth scroll */
}

.boxChild {
  margin: 600px 0 300px;
  width: 40px;
  height: 40px;
  background: green;
}
<button>Scroll to element</button>
<div class='box'>
  <div class='boxChild'></div>
</div>

Methode 3 - Verwenden des CSS -Bildlaufverhaltens :

.box {
  width: 80%;
  border: 2px dashed;
  height: 180px;
  overflow-y: scroll;
  scroll-behavior: smooth; /* <--- */
}

#boxChild {
  margin: 600px 0 300px;
  width: 40px;
  height: 40px;
  background: green;
}
<a href='#boxChild'>Scroll to element</a>
<div class='box'>
  <div id='boxChild'></div>
</div>

vsync
quelle
1
Beachten Sie, dass das Scroll-Verhalten in IE / Edge / Safari nicht unterstützt wird
Uhr
1
@sheats - es steht genau das in dem MDN-Dokumentationslink, den ich in großer Schriftgröße platziert hatte. Auch wenn es für diese Browser nicht funktioniert, heißt das nicht, dass Sie es nicht verwenden sollten. Es gibt keine "Regel". Alles muss sich in allen Browsern gleich verhalten. Wenn moderne Browser zaubern können, lassen Sie sie zaubern.
vsync
In diesem Beitrag geht es eher um das Scrollen des gesamten Dokuments als um ein scrollbares Element.
@ DoMiNeLa10 - Das ist eine Annahme. OP könnte ein willkürliches Beispiel geliefert haben, das sein / ihr Problem veranschaulichen sollte. Auch OP ist nicht das Hauptanliegen, sondern die Leute, die von Suchmaschinen kommen, die nach einer gesunden Lösung suchen, und die höchstwahrscheinlich speziell auf OP-Bedürfnisse reagieren, werden ihnen nicht helfen, und das Ziel dieser Website ist es, solide Antworten zu erstellen , die ebenso vielen helfen können wie möglich. Meine Antwort liefert beides .
vsync
12

Um ein Element nur bei Bedarf in die Ansicht eines Div zu scrollen, können Sie folgende scrollIfNeededFunktion verwenden:

function scrollIfNeeded(element, container) {
  if (element.offsetTop < container.scrollTop) {
    container.scrollTop = element.offsetTop;
  } else {
    const offsetBottom = element.offsetTop + element.offsetHeight;
    const scrollBottom = container.scrollTop + container.offsetHeight;
    if (offsetBottom > scrollBottom) {
      container.scrollTop = offsetBottom - container.offsetHeight;
    }
  }
}

document.getElementById('btn').addEventListener('click', ev => {
  ev.preventDefault();
  scrollIfNeeded(document.getElementById('goose'), document.getElementById('container'));
});
.scrollContainer {
  overflow-y: auto;
  max-height: 100px;
  position: relative;
  border: 1px solid red;
  width: 120px;
}

body {
  padding: 10px;
}

.box {
  margin: 5px;
  background-color: yellow;
  height: 25px;
  display: flex;
  align-items: center;
  justify-content: center;
}

#goose {
  background-color: lime;
}
<div id="container" class="scrollContainer">
  <div class="box">duck</div>
  <div class="box">duck</div>
  <div class="box">duck</div>
  <div class="box">duck</div>
  <div class="box">duck</div>
  <div class="box">duck</div>
  <div class="box">duck</div>
  <div class="box">duck</div>
  <div id="goose" class="box">goose</div>
  <div class="box">duck</div>
  <div class="box">duck</div>
  <div class="box">duck</div>
  <div class="box">duck</div>
</div>

<button id="btn">scroll to goose</button>

mpen
quelle
1
Das war wirklich hilfreich. Ich kämpfte ein bisschen, weil ich die Position verpasst hatte: relativ auf dem Container. Das war entscheidend!
Brohr
11

Code sollte sein:

var divElem = document.getElementById('scrolling_div');
var chElem = document.getElementById('element_within_div');
var topPos = divElem.offsetTop;
divElem.scrollTop = topPos - chElem.offsetTop;

Sie möchten den Unterschied zwischen der obersten Position des Kindes und der obersten Position des Divs scrollen.

Erhalten Sie Zugriff auf untergeordnete Elemente mit:

var divElem = document.getElementById('scrolling_div'); 
var numChildren = divElem.childNodes.length;

und so weiter....

pgp
quelle
1
Sollte nicht die 2. Zeile tatsächlich lesen var chElem = document.getElementById('element_within_div');und die 3. Zeile lesen var topPos = divElem.offsetTop;?
Jayp
7

Wenn Sie jQuery verwenden, können Sie mit einer Animation wie folgt scrollen:

$(MyContainerDiv).animate({scrollTop: $(MyContainerDiv).scrollTop() + ($('element_within_div').offset().top - $(MyContainerDiv).offset().top)});

Die Animation ist optional: Sie können den oben berechneten scrollTop-Wert auch direkt in die scrollTop- Eigenschaft des Containers einfügen .

Dlauzon
quelle
5

Native JS, Cross Browser, Smooth Scroll (Update 2020)

Die Einstellung ScrollTopführt zwar zum gewünschten Ergebnis, der Bildlauf ist jedoch sehr abrupt. Die Verwendung eines jqueryreibungslosen Bildlaufs war keine Option. Hier ist eine native Methode, um die Aufgabe zu erledigen, die alle gängigen Browser unterstützt. Referenz - caniuse

// get the "Div" inside which you wish to scroll (i.e. the container element)
const El = document.getElementById('xyz');

// Lets say you wish to scroll by 100px, 
El.scrollTo({top: 100, behavior: 'smooth'});

// If you wish to scroll until the end of the container
El.scrollTo({top: El.scrollHeight, behavior: 'smooth'});

Das ist es!


Und hier ist ein funktionierender Ausschnitt für die Zweifler -

document.getElementById('btn').addEventListener('click', e => {
  e.preventDefault();
  // smooth scroll
  document.getElementById('container').scrollTo({top: 175, behavior: 'smooth'});
});
/* just some styling for you to ignore */
.scrollContainer {
  overflow-y: auto;
  max-height: 100px;
  position: relative;
  border: 1px solid red;
  width: 120px;
}

body {
  padding: 10px;
}

.box {
  margin: 5px;
  background-color: yellow;
  height: 25px;
  display: flex;
  align-items: center;
  justify-content: center;
}

#goose {
  background-color: lime;
}
<!-- Dummy html to be ignored -->
<div id="container" class="scrollContainer">
  <div class="box">duck</div>
  <div class="box">duck</div>
  <div class="box">duck</div>
  <div class="box">duck</div>
  <div class="box">duck</div>
  <div class="box">duck</div>
  <div class="box">duck</div>
  <div class="box">duck</div>
  <div id="goose" class="box">goose</div>
  <div class="box">duck</div>
  <div class="box">duck</div>
  <div class="box">duck</div>
  <div class="box">duck</div>
</div>

<button id="btn">goose</button>

Update: Wie Sie in den Kommentaren sehen können, scheint Element.scrollTo()dies in IE11 nicht unterstützt zu werden. Wenn Sie sich also nicht für IE11 interessieren (das sollten Sie wirklich nicht), können Sie dies in all Ihren Projekten verwenden. Beachten Sie, dass Edge unterstützt wird! Sie lassen Ihre Edge / Windows-Benutzer also nicht wirklich zurück;)

Referenz

Niket Pathak
quelle
1
scrollTo()wird möglicherweise in allen gängigen Browsern für WindowObjekte unterstützt, wird jedoch in IE oder Edge für Elemente nicht unterstützt.
Tim Down
Laut caniuse wird es in IE11 und Edge unterstützt. Ich habe in diesen Browsern nicht persönlich getestet, aber es scheint unterstützt zu werden.
Niket Pathak
1
Das ist window.scrollTonicht so Element.scrollTo. Versuchen Sie dies beispielsweise in Edge und überprüfen Sie die Konsole: codepen.io/timdown/pen/abzVEMB
Tim Down
Du hast recht. IE11 wird nicht unterstützt. Jedoch V76 Edge - (ref) und scheint oben unterstützt zu werden
Niket Pathak
2

Es gibt zwei Tatsachen:

1) Die Komponente scrollIntoView wird von Safari nicht unterstützt.

2) JS Framework jQuery kann die Arbeit folgendermaßen erledigen:

parent = 'some parent div has css position==="fixed"' || 'html, body';

$(parent).animate({scrollTop: $(child).offset().top}, duration)
Nickmit
quelle
1

Hier ist eine einfache reine JavaScript-Lösung, die für eine Zielnummer (Wert für scrollTop), ein Ziel-DOM-Element oder einige spezielle String-Fälle funktioniert :

/**
 * target - target to scroll to (DOM element, scrollTop Number, 'top', or 'bottom'
 * containerEl - DOM element for the container with scrollbars
 */
var scrollToTarget = function(target, containerEl) {
    // Moved up here for readability:
    var isElement = target && target.nodeType === 1,
        isNumber = Object.prototype.toString.call(target) === '[object Number]';

    if (isElement) {
        containerEl.scrollTop = target.offsetTop;
    } else if (isNumber) {
        containerEl.scrollTop = target;
    } else if (target === 'bottom') {
        containerEl.scrollTop = containerEl.scrollHeight - containerEl.offsetHeight;
    } else if (target === 'top') {
        containerEl.scrollTop = 0;
    }
};

Und hier sind einige Anwendungsbeispiele:

// Scroll to the top
var scrollableDiv = document.getElementById('scrollable_div');
scrollToTarget('top', scrollableDiv);

oder

// Scroll to 200px from the top
var scrollableDiv = document.getElementById('scrollable_div');
scrollToTarget(200, scrollableDiv);

oder

// Scroll to targetElement
var scrollableDiv = document.getElementById('scrollable_div');
var targetElement= document.getElementById('target_element');
scrollToTarget(targetElement, scrollableDiv);
Klacks
quelle
1

Ein weiteres Beispiel für die Verwendung von jQuery und animieren.

var container = $('#container');
var element = $('#element');

container.animate({
    scrollTop: container.scrollTop = container.scrollTop() + element.offset().top - container.offset().top
}, {
    duration: 1000,
    specialEasing: {
        width: 'linear',
        height: 'easeOutBounce'
    },
    complete: function (e) {
        console.log("animation completed");
    }
});
Hoffnungsträger
quelle
0

Benutzeranimiertes Scrollen

Hier ist ein Beispiel für das programmgesteuerte <div>horizontale Scrollen ohne JQuery . Zum Scrollen vertikal, würden Sie JavaScripts schreiben ersetzen scrollLeftmit scrollTop, statt.

JSFiddle

https://jsfiddle.net/fNPvf/38536/

HTML

<!-- Left Button. -->
<div style="float:left;">
    <!-- (1) Whilst it's pressed, increment the scroll. When we release, clear the timer to stop recursive scroll calls. -->
    <input type="button" value="«" style="height: 100px;" onmousedown="scroll('scroller',3, 10);" onmouseup="clearTimeout(TIMER_SCROLL);"/>
</div>
<!-- Contents to scroll. -->
<div id="scroller" style="float: left; width: 100px; height: 100px; overflow: hidden;">
    <!-- <3 -->
    <img src="https://cdn.sstatic.net/Sites/stackoverflow/company/img/logos/so/so-logo.png?v=9c558ec15d8a" alt="image large" style="height: 100px" />
</div>
<!-- Right Button. -->
<div style="float:left;">
    <!-- As (1). (Use a negative value of 'd' to decrease the scroll.) -->
    <input type="button" value="»" style="height: 100px;" onmousedown="scroll('scroller',-3, 10);" onmouseup="clearTimeout(TIMER_SCROLL);"/>
</div>

JavaScript

// Declare the Shared Timer.
var TIMER_SCROLL;
/** 
Scroll function. 
@param id  Unique id of element to scroll.
@param d   Amount of pixels to scroll per sleep.
@param del Size of the sleep (ms).*/
function scroll(id, d, del){
    // Scroll the element.
    document.getElementById(id).scrollLeft += d;
    // Perform a delay before recursing this function again.
    TIMER_SCROLL = setTimeout("scroll('"+id+"',"+d+", "+del+");", del);
 }

Gutschrift an Dux .


Automatisch animiertes Scrollen

Darüber hinaus finden Sie hier Funktionen zum <div>vollständigen Scrollen nach links und rechts. Das einzige, was wir hier ändern, ist, dass wir überprüfen, ob die vollständige Erweiterung des Bildlaufs verwendet wurde, bevor wir einen rekursiven Aufruf zum erneuten Bildlauf ausführen.

JSFiddle

https://jsfiddle.net/0nLc2fhh/1/

HTML

<!-- Left Button. -->
<div style="float:left;">
    <!-- (1) Whilst it's pressed, increment the scroll. When we release, clear the timer to stop recursive scroll calls. -->
    <input type="button" value="«" style="height: 100px;" onclick="scrollFullyLeft('scroller',3, 10);"/>
</div>
<!-- Contents to scroll. -->
<div id="scroller" style="float: left; width: 100px; height: 100px; overflow: hidden;">
  <!-- <3 -->
  <img src="https://cdn.sstatic.net/Sites/stackoverflow/company/img/logos/so/so-logo.png?v=9c558ec15d8a" alt="image large" style="height: 100px" />
</div>
<!-- Right Button. -->
<div style="float:left;">
    <!-- As (1). (Use a negative value of 'd' to decrease the scroll.) -->
    <input type="button" value="»" style="height: 100px;" onclick="scrollFullyRight('scroller',3, 10);"/>
</div>

JavaScript

// Declare the Shared Timer.
var TIMER_SCROLL;
/** 
Scroll fully left function; completely scrolls  a <div> to the left, as far as it will go.
@param id  Unique id of element to scroll.
@param d   Amount of pixels to scroll per sleep.
@param del Size of the sleep (ms).*/
function scrollFullyLeft(id, d, del){
    // Fetch the element.
    var el = document.getElementById(id);
    // Scroll the element.
    el.scrollLeft += d;
    // Have we not finished scrolling yet?
    if(el.scrollLeft < (el.scrollWidth - el.clientWidth)) {
        TIMER_SCROLL = setTimeout("scrollFullyLeft('"+id+"',"+d+", "+del+");", del);
    }
}

/** 
Scroll fully right function; completely scrolls  a <div> to the right, as far as it will go.
@param id  Unique id of element to scroll.
@param d   Amount of pixels to scroll per sleep.
@param del Size of the sleep (ms).*/
function scrollFullyRight(id, d, del){
    // Fetch the element.
    var el = document.getElementById(id);
    // Scroll the element.
    el.scrollLeft -= d;
    // Have we not finished scrolling yet?
    if(el.scrollLeft > 0) {
        TIMER_SCROLL = setTimeout("scrollFullyRight('"+id+"',"+d+", "+del+");", del);
    }
}
Mapsy
quelle
0

Das hat mir endlich gedient

/** Set parent scroll to show element
 * @param element {object} The HTML object to show
 * @param parent {object} The HTML object where the element is shown  */
var scrollToView = function(element, parent) {
    //Algorithm: Accumulate the height of the previous elements and add half the height of the parent
    var offsetAccumulator = 0;
    parent = $(parent);
    parent.children().each(function() {
        if(this == element) {
            return false; //brake each loop
        }
        offsetAccumulator += $(this).innerHeight();
    });
    parent.scrollTop(offsetAccumulator - parent.innerHeight()/2);
}
Iñigo Panera
quelle
0

Der Browser scrollt automatisch zu einem Element, das den Fokus erhält. Sie können also auch das Element umbrechen, in das Sie scrollen möchten, <a>...</a>und dann, wenn Sie einen Bildlauf benötigen, den Fokus darauf setzena

Dreizack D'Gao
quelle
0

Verwenden Sie nach Auswahl des Elements einfach die scrollIntoViewFunktion mit der folgenden Option:

const option = {
  top: 0, // number,
  left: 0, // number,
  behavior: 'auto', // auto or smooth 
    // - auto for one jump motion and smooth for animated motion -
};

Die Antwort für diesen Beitrag lautet also:

const el = document.getElementById('id-name');
el.scrollIntoView({
  top: 0,
  left: 0,
  behavior: 'auto',
});
AmerllicA
quelle
0

Wenn Sie ein div-Element haben, in das Sie scrollen müssen, versuchen Sie diesen Code

document.querySelector('div').scroll(x,y)

Dies funktioniert bei mir in einem Div mit einer Schriftrolle. Dies sollte bei Ihnen funktionieren, falls Sie mit der Maus über dieses Element zeigen und dann versuchen, nach unten oder oben zu scrollen. Wenn es manuell funktioniert, sollte es auch funktionieren

Amado Saladino
quelle