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

171

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

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

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

Я хочу сказать это так

MyContainerDiv.getElementById(chr).scrollIntoView(true);
Амр Элгархи
источник
Scrolltop не всегда возвращает полезное значение. Я склонен использовать SetTimeoutв $(document).ready({})функции и установить focus()элемент, к которому вы хотите перейти. Работает для меня
DerpyNerd

Ответы:

343

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

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

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

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

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

Если вы используете прототип JS Framework, вы должны сделать то же самое, как это:

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

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

Брайан Барретт
источник
9
Это было действительно полезно! Если вы хотите установить прокрутку несколько раз, вам нужно сместить текущее местоположение прокрутки. Вот как я это сделал в jQuery: $ ('# scrolling_div'). ScrollTop ($ ('# scrolling_div'). ScrollTop () + $ ('# element_within_div'). Position (). Top);
Будет
3
Остерегайтесь того, что запрос myElement.offsetTopвызовет перекомпоновку (перебивание макета), которая может стать узким местом
Kestutis
27
Не забудьте установить родительский position: relativeэлемент прокрутки с помощью css: в противном случае вы потратите много времени на отладку, как я только что сделал.
сохранено
2
Мне пришлось установить overflow-yсвойство scrollдля родительского элемента ( scrolling_div), в противном случае оно не работало. Значение css по умолчанию для этого overflowсвойства - autoи хотя это также делает возможной ручную прокрутку, код js не будет работать (даже с {psition: relative}..)
Евгения Манолова
2
По-прежнему работает в 2017 году. Дополнительная информация: .offsetTop может вернуть 0. Затем вы должны обратиться к родительскому элементу и повторить попытку. Я сделал это для тегов, h4а divзатем articleтег и articleработал только для меня.
Фенио
66

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

divElem.scrollTop = 0;

Обновление :

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

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

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

Метод 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>

VSync
источник
1
Обратите внимание, что поведение прокрутки не поддерживается в IE / Edge / Safari
sheats
1
@sheats - это говорит именно то, что в ссылке на документацию MDN, которую я поместил большим шрифтом. Даже если он не работает для этих браузеров, это не значит, что вы не должны его использовать. Не существует «правила», все должно работать одинаково во всех браузерах. Если современные браузеры могут творить магию, пусть они делают магию.
vsync
Этот пост посвящен прокрутке всего документа, а не прокручиваемому элементу.
@ DoMiNeLa10 - это предположение. ОП, возможно, предоставил произвольный пример, который должен был проиллюстрировать его / ее проблему. Кроме того, OP - не главная проблема, а скорее люди из поисковых систем, которые ищут полезное решение, и, скорее всего, конкретный ответ на запросы OP им не поможет, и цель этого веб-сайта - найти четкие ответы, которые могут помочь как можно большему числу людей. насколько это возможно. Мой ответ дает оба .
vsync
12

Чтобы прокрутить элемент в поле зрения 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>

mpen
источник
1
Это было действительно полезно. Я немного боролся, потому что я пропустил позицию: относительно контейнера. Это было важно!
Брор
11

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

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;

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

PGP
источник
1
Разве 2-я строка не должна читать, var chElem = document.getElementById('element_within_div');а 3-я строка читать var topPos = divElem.offsetTop;?
Джайп
7

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

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

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

dlauzon
источник
5

Родной 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'});

Это оно!


А вот рабочий фрагмент для сомнительных -

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 позади;)

Ссылка

Никет патхак
источник
1
scrollTo()может поддерживаться во всех основных браузерах для Windowобъектов, но не поддерживается в IE или Edge для элементов.
Тим Даун
Согласно caniuse , это поддерживается в IE11 и Edge. Не проверял лично на этих браузерах, но, кажется, поддерживается.
Никет Патхак
1
Это window.scrollToне так Element.scrollTo. Попробуйте это в Edge, например, и проверьте консоль: codepen.io/timdown/pen/abzVEMB
Тим Даун
Ты прав. IE11 не поддерживается. Тем не менее, Edge v76 (ref) и выше, кажется, поддерживаются
Niket Pathak
2

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

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

2) JS Framework JQuery может сделать работу следующим образом:

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

$(parent).animate({scrollTop: $(child).offset().top}, duration)
nickmit
источник
1

Вот простое чистое решение 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);

или

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

или

// Scroll to targetElement
var scrollableDiv = document.getElementById('scrollable_div');
var targetElement= document.getElementById('target_element');
scrollToTarget(targetElement, scrollableDiv);
NoBrainer
источник
1

Еще один пример использования 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");
    }
});
Hopefulee
источник
0

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

Вот пример того, как программно прокрутить <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);
 }

Кредит Дуксу .


Авто Анимированная Прокрутка

Кроме того, здесь есть функции для прокрутки <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);
    }
}
Mapsy
источник
0

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

/** 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);
}
Иньиго Панера
источник
0

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

Трезубец д'Гао
источник
0

После выбора элемента просто используйте scrollIntoViewфункцию с опцией ниже:

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

Таким образом, ответ на этот пост:

const el = document.getElementById('id-name');
el.scrollIntoView({
  top: 0,
  left: 0,
  behavior: 'auto',
});
AmerllicA
источник
0

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

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

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

Амадо Саладино
источник