Как перейти к элементу внутри div?

У меня есть прокручиваемый div, и я хочу, чтобы при нажатии на него было событие, оно заставит этот div прокручиваться, чтобы просмотреть элемент внутри. Я написал его JavasSript так:

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

но это прокручивает всю страницу при прокрутке самого div. Как это исправить?

Я хочу сказать это так: MyContainerDiv.getElementById(chr).scrollIntoView(true);


person Amr Elgarhy    schedule 11.03.2009    source источник
comment
Scrolltop не всегда возвращает полезное значение. Я обычно использую SetTimeout в функции $(document).ready({}) и устанавливаю focus() для элемента, к которому вы хотите перейти. Работает для меня   -  person DerpyNerd    schedule 30.08.2016


Ответы (15)


Вам нужно получить верхнее смещение элемента, который вы хотите прокрутить, относительно его родителя (прокручиваемого контейнера div):

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

Переменная topPos теперь установлена ​​на расстояние между верхом прокручиваемого div и элементом, который вы хотите видеть (в пикселях).

Теперь мы говорим div, чтобы он переместился в эту позицию, используя scrollTop:

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

Если вы используете прототип JS-фреймворка, сделайте то же самое:

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

Опять же, это прокрутит div так, чтобы элемент, который вы хотите увидеть, был точно вверху (или, если это невозможно, прокрутите его как можно дальше вниз, чтобы он был виден).

person Brian Barrett    schedule 20.10.2009
comment
Это было действительно полезно! Если вы хотите установить прокрутку несколько раз, вам нужно компенсировать текущее местоположение прокрутки. Вот как я это сделал в jQuery: $ ('# scrolling_div'). ScrollTop ($ ('# scrolling_div'). ScrollTop () + $ ('# element_within_div'). Position (). Top); - person Will; 14.08.2014
comment
больше не работает, offsetTop всегда равен 0 - person singe3; 03.04.2015
comment
Помните, что запрос myElement.offsetTop вызовет перекомпоновку (изменение макета), которая может быть узкое место производительности - person Kestutis; 09.08.2016
comment
Не забудьте установить родителя прокрутки с помощью css: position: relative, иначе вы потратите много времени на отладку, как только что сделал я. - person savedario; 04.02.2017
comment
Мне пришлось установить для свойства overflow-y значение scroll для родительского элемента (scrolling_div), иначе это не сработало. Значение css по умолчанию для свойства overflow - auto, и хотя оно также делает возможной ручную прокрутку, код js не будет работать (даже с {psition: relative} ..) - person Evgeniya Manolova; 26.02.2017
comment
По-прежнему работает в 2017 году. Дополнительная информация: .offsetTop может возвращать 0. Затем вам следует обратиться к родительскому элементу и повторить попытку. Я сделал это для тегов h4, затем div, затем article, и только article у меня сработало. - person Fenio; 07.11.2017
comment
Это лучшее решение, которое я нашел до сих пор, TY - person M.Abulsoud; 24.10.2018
comment
Очень хорошо! Отличное решение. - person Sandeep Deb; 13.05.2019
comment
@savedario Это должно быть задокументировано в этом ответе. - person Thanh Nguyen; 18.06.2020
comment
люблю тебя, чувак - стоит отметить, добавьте этот CSS ... scroll-behavior: smooth; ... чтобы сделать прокрутку анимированной и плавной (добавьте ее в div с помощью полосы прокрутки) - person danday74; 16.07.2021

Вам нужно будет найти позицию элемента в DIV, к которому вы хотите прокрутить, и установить свойство scrollTop.

divElem.scrollTop = 0;

Обновить:

Пример кода для перемещения вверх или вниз

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

  function move_down() {
    document.getElementById('divElem').scrollTop -= 10;
  }
person Glennular    schedule 11.03.2009
comment
Я хочу прокрутить его, чтобы увидеть, что он не прокручивается с определенным значением - person Amr Elgarhy; 11.03.2009

Метод 1 - плавная прокрутка к элементу внутри элемента

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>

Метод 2 - Использование Element.scrollIntoView:

Обратите внимание, что поддержка браузера не очень хороша для Вот этот

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>

Метод 3. Использование поведения прокрутки CSS:

.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>

person vsync    schedule 23.06.2018
comment
Обратите внимание, что поведение прокрутки не поддерживается в IE / Edge / Safari. - person sheats; 24.02.2019
comment
@sheats - это именно то, что написано в ссылке на документацию MDN, которую я поместил крупным шрифтом. Даже если он не работает в этих браузерах, это не значит, что вам не следует его использовать. Нет правила, что все должно вести себя одинаково во всех браузерах. Если современные браузеры могут творить чудеса, позвольте им творить чудеса. - person vsync; 24.02.2019
comment
Этот пост о прокрутке всего документа, а не о прокручиваемом элементе. - person ; 29.07.2019
comment
@ DoMiNeLa10 - Это предположение. OP мог бы привести произвольный пример, который призван проиллюстрировать его / ее проблему. Кроме того, OP не является главной проблемой, а скорее люди, приходящие из поисковых систем, которые ищут полезное решение, и, скорее всего, конкретный ответ на потребности OP не поможет им, и цель этого веб-сайта - создать надежное ответы, которые могут помочь как можно большему количеству людей. Мой ответ дает и то, и другое. - person vsync; 29.07.2019

Собственный JS, кроссбраузер, плавная прокрутка (обновление 2020)

Установка ScrollTop дает желаемый результат, но прокрутка очень резкая. Использование jquery для плавной прокрутки не было вариантом. Итак, вот собственный способ выполнить работу, поддерживающий все основные браузеры. Ссылка - 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'});

Вот и все!


And here's a working snippet for the doubtful -

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>

Обновление: Как вы можете заметить из комментариев, похоже, что Element.scrollTo() не поддерживается в IE11. Так что, если вас не волнует IE11 (на самом деле, не стоит), не стесняйтесь использовать его во всех своих проектах. Обратите внимание, что существует поддержка Edge! Так что вы на самом деле не бросаете пользователей Edge / Windows;)

Справочник

person Niket Pathak    schedule 10.12.2019
comment
scrollTo() может поддерживаться во всех основных браузерах для Window объектов, но не поддерживается в IE или Edge для элементов. - person Tim Down; 03.01.2020
comment
Согласно caniuse, он поддерживается в IE11 и Edge. Не тестировал лично в этих браузерах, но вроде поддерживается. - person Niket Pathak; 03.01.2020
comment
Это window.scrollTo, а не Element.scrollTo. Попробуйте это в Edge, например, и проверьте консоль: codepen.io/timdown/pen/abzVEMB - person Tim Down; 03.01.2020
comment
Ты прав. IE11 не поддерживается. Однако Edge v76 (ref) и выше, похоже, поддерживаться - person Niket Pathak; 06.01.2020

Чтобы прокрутить элемент до отображения div, вы можете использовать эту scrollIfNeeded функцию только в случае необходимости:

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>

person mpen    schedule 24.08.2017
comment
Это было действительно полезно. Я немного боролся, потому что пропустил позицию: относительная на контейнере. Это было очень важно! - person brohr; 18.05.2018

Код должен быть:

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

Вы хотите прокрутить разницу между верхним положением дочернего элемента и верхним положением div.

Получите доступ к дочерним элементам, используя:

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

и так далее....

person pgp    schedule 19.10.2015
comment
Разве 2-я строка не должна читать var chElem = document.getElementById('element_within_div');, а 3-я строка - var topPos = divElem.offsetTop;? - person jayp; 26.03.2016

Если вы используете jQuery, вы можете прокручивать анимацию, используя следующее:

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

Анимация является необязательной: вы также можете взять вычисленное выше значение scrollTop и поместить его непосредственно в scrollTop.

person dlauzon    schedule 20.06.2017

Мы можем решить эту проблему без использования JQuery и других библиотек.

Для этого я написал следующий код:

У вас похожая структура - ›

<div class="parent">
  <div class="child-one">

  </div>
  <div class="child-two">

  </div>
</div>

JS:

scrollToElement() {
  var parentElement = document.querySelector('.parent');
  var childElement = document.querySelector('.child-two');

  parentElement.scrollTop = childElement.offsetTop - parentElement.offsetTop;
}

Мы можем легко переписать этот метод для передачи родительского и дочернего в качестве аргументов.

person spirito_libero    schedule 24.08.2020

Есть два факта:

1) Компонент scrollIntoView не поддерживается сафари.

2) JS framework jQuery может выполнять такую ​​работу:

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

$(parent).animate({scrollTop: $(child).offset().top}, duration)
person nickmit    schedule 05.03.2019

Вот простое решение на чистом JavaScript, которое работает для целевого числа (значение для scrollTop), целевого элемента DOM или некоторых особых случаев String:

/**
 * 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;
    }
};

А вот несколько примеров использования:

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

or

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

or

// Scroll to targetElement
var scrollableDiv = document.getElementById('scrollable_div');
var targetElement= document.getElementById('target_element');
scrollToTarget(targetElement, scrollableDiv);
person NoBrainer    schedule 24.01.2018

Еще один пример использования jQuery и animate.

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");
    }
});
person Hopefulee    schedule 22.05.2018

Прокрутка с пользовательской анимацией

Вот пример того, как программно прокручивать <div> по горизонтали без JQuery. Для вертикальной прокрутки вместо этого вы должны заменить запись JavaScript в scrollLeft на scrollTop.

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

Кредит Dux.


Автоматическая анимированная прокрутка

Кроме того, здесь есть функции для полной прокрутки <div> влево и вправо. Единственное, что мы здесь изменяем, - это проверяем, было ли использовано полное расширение прокрутки, прежде чем делать рекурсивный вызов для повторной прокрутки.

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);
    }
}
person Mapsy    schedule 06.04.2017

Это то, что наконец послужило мне

/** 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);
}
person Iñigo Panera    schedule 27.02.2018

учитывая, что у вас есть элемент div, который вам нужно прокрутить внутри, попробуйте этот фрагмент кода

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

это работает со мной внутри div с прокруткой, это должно сработать с вами, если вы навели указатель мыши на этот элемент, а затем попытались прокрутить вниз или вверх. Если он работает вручную, он тоже должен работать

person Amado Saladino    schedule 20.05.2020

браузер автоматически выполняет прокрутку к элементу, который получает фокус, поэтому вы также можете сделать это, чтобы обернуть элемент, который вам нужно прокрутить, в <a>...</a>, а затем, когда вам нужно прокрутить, просто установите фокус на этом a

person Trident D'Gao    schedule 21.03.2019