Прокрутить до нижней части div?


808

Я создаю чат, используя ajax-запросы в rails, и пытаюсь получить div для прокрутки до дна без особой удачи.

Я оборачиваю все в этом div:

#scroll {
    height:400px;
    overflow:scroll;
}

Есть ли способ сохранить прокрутку вниз по умолчанию с помощью JS?

Есть ли способ сохранить прокрутку вниз после запроса ajax?

Ответы:


1326

Вот что я использую на своем сайте:

var objDiv = document.getElementById("your_div");
objDiv.scrollTop = objDiv.scrollHeight;

13
этот метод подходит для всех браузеров?
Jondinham

1
@PaulDinh: я только что посмотрел на это, и есть проблема с IE7 и ниже, используя scrollHeight. Кажется, здесь есть обходной путь для IE7 .
Шон

3
Почему это не работает после динамического добавления элементов в div?
Винс

3
@ Винс - это разовая сделка. Если вы измените содержимое, вам нужно будет выполнить его заново. Команда в основном говорит «переместить полосу прокрутки в эту позицию».
DrFriedParts

8
Кроме того, если у вас есть элементы, например, внутри элемента div, вы можете прокрутить определенный элемент в поле зрения. (т.е. элемент виден внутри родительского элемента div) .. примерно так: $ ("#" + instanceID) .scrollTop ($ ("#" + instanceID) [0] .scrollIntoView);
netfed

360

Это намного проще, если вы используете jQuery scrollTop :

$("#mydiv").scrollTop($("#mydiv")[0].scrollHeight);

273
Как это проще?
captainspi

78
1 строка вместо 2? понятия не имею, но то, что вы можете легко сделать с помощью JQuery - это анимировать действие следующим образом: $ ("# div-id"). animate ({scrollTop: $ ("# div-id") [0] .scrollHeight}, 1000 ); надеюсь, это кому-нибудь поможет :)
Самуил

28
вам нужно [0], чтобы получить элемент dom из элемента jquery, чтобы получить scrollHeight
Джимми Боссе

14
«Не говоря уже о том, что JQ труднее читать / понимать!» Чисто мнение. Я, например, считаю, что JQuery намного легче читать, понимать и делать вещи. И это решение лучше, если вы уже используете JQuery.
Ханна

47
Не повторяя себя:$("#mydiv").scrollTop(function() { return this.scrollHeight; });
Эрик

98

Вы можете использовать следующий код:

function scrollToBottom (id) {
   var div = document.getElementById(id);
   div.scrollTop = div.scrollHeight - div.clientHeight;
}

Чтобы выполнить плавную прокрутку с помощью JQuery:

function scrollSmoothToBottom (id) {
   var div = document.getElementById(id);
   $('#' + id).animate({
      scrollTop: div.scrollHeight - div.clientHeight
   }, 500);
}

Смотрите пример на JSFiddle

Вот почему это работает:

введите описание изображения здесь

Ref: scrollTop , scrollHeight , clientHeight


92

используя jQuery animate :

$('#DebugContainer').stop().animate({
  scrollTop: $('#DebugContainer')[0].scrollHeight
}, 800);

5
Это то, что Сэм сказал в этом комментарии . Это, вероятно, более полезно в реальном ответе, хотя!
Квентин Праде

6
Обратите внимание, как этот ответ использует .stop () , что предотвращает проблемы с несколькими анимациями.
Kalyfe

Удивительно, но это единственный, который работает для меня из всех ответов ранее. Это может быть из-за того, как мои другие элементы расположены вокруг слоя, который должен продолжать прокручиваться
Duniyadnd

Это был единственный, который работал для меня (я добавляю изображения, а не текст)
Джон Ktejik

36
var mydiv = $("#scroll");
mydiv.scrollTop(mydiv.prop("scrollHeight"));

Работает с JQuery 1.6

https://api.jquery.com/scrollTop/

http://api.jquery.com/prop/


1
Это решение работает для элементов с уникальным классом CSS, но без идентификатора CSS. Решение верхнего комментария не работает "из коробки" с классом CSS.
CFitz

31

Более новый метод, который работает во всех текущих браузерах :

this.scrollIntoView(false);

1
Думаю, это работает только в Firefox: developer.mozilla.org/en/docs/Web/API/Element/…
Амрит Кахлон,

3
Поддержке действительно не хватает банкомата, но если это будет принято, то это будет здорово.
Кристьян Лиива

Любые обновления? Я чувствую, что это должно быть принято как хороший ответ. Я имею в виду, давай jQuery?
1

working: document.querySelector (". mdl-list"). scrollIntoView (false);
Иоганн Медина

15

плавная прокрутка с помощью Javascript:

document.getElementById('messages').scrollIntoView({ behavior: 'smooth', block: 'end' });


8

Если вы не хотите полагаться scrollHeight, поможет следующий код:

$('#scroll').scrollTop(1000000);

1
Похоже, что ни одно из вышеперечисленных решений, в том числе и ваше, не работает на Firefox на Android ... есть мысли, пожалуйста?
Тост Кая

Неважно, я использовал слишком большое число ( 1E10). Меньшее число работ
andrewtweber

Это всегда важно
Бен Талиадорос

4
Почему это было бы плохое выступление? Это не так, как это повторяется по каждому пикселю. Теперь плохая практика - это другой вопрос…
devios1

$ ('# scroll'). scrollTop (Infinity), тогда это тоже должно работать.
Мадхав

5

Используя jQuery, scrollTop используется для установки вертикальной позиции полосы прокрутки для любого данного элемента. есть также хороший плагин jquery scrollTo, используемый для прокрутки с анимацией и различными опциями ( демонстрациями )

var myDiv = $("#div_id").get(0);
myDiv.scrollTop = myDiv.scrollHeight;

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

var myDiv = $("#div_id").get(0);
myDiv.animate({
    scrollTop: myDiv.scrollHeight
  }, 500);

4

Я столкнулся с той же проблемой, но с дополнительным ограничением: у меня не было контроля над кодом, добавляющим новые элементы в контейнер прокрутки. Ни один из приведенных здесь примеров не позволил мне сделать именно это. Вот решение, которое я выбрал.

Он использует Mutation Observers( https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver ), что позволяет использовать его только в современных браузерах (хотя существуют многозаполнения)

Так что в основном код делает именно это:

var scrollContainer = document.getElementById("myId");

// Define the Mutation Observer
var observer = new MutationObserver(function(mutations) {

  // Compute sum of the heights of added Nodes
  var newNodesHeight = mutations.reduce(function(sum, mutation) {
      return sum + [].slice.call(mutation.addedNodes)
        .map(function (node) { return node.scrollHeight || 0; })
        .reduce(function(sum, height) {return sum + height});
  }, 0);

  // Scroll to bottom if it was already scrolled to bottom
  if (scrollContainer.clientHeight + scrollContainer.scrollTop + newNodesHeight + 10 >= scrollContainer.scrollHeight) {
    scrollContainer.scrollTop = scrollContainer.scrollHeight;
  }

});

// Observe the DOM Element
observer.observe(scrollContainer, {childList: true});

Я сделал скрипку, чтобы продемонстрировать концепцию: https://jsfiddle.net/j17r4bnk/


как получить динамический идентификатор? как в <div class="abc"><div data-bind=attr : {'id': myId } ></div></div>В этом коде myId является переменной. Как я могу получить доступ к этому идентификатору в скрипте.
Ирфан Юсаниф

Я не совсем уверен, что понимаю ваш вопрос. В моем примере «myId» - это идентификатор контейнера прокрутки. Хотите создать более одной области, где пользователь может прокручивать?
Benkinass

4

Javascript или JQuery:

var scroll = document.getElementById('messages');
   scroll.scrollTop = scroll.scrollHeight;
   scroll.animate({scrollTop: scroll.scrollHeight});

Css:

 .messages
 {
      height: 100%;
      overflow: auto;
  }

4

Нашел это действительно полезным, спасибо.

Для пользователей Angular 1.X:

angular.module('myApp').controller('myController', ['$scope', '$document',
  function($scope, $document) {

    var overflowScrollElement = $document[0].getElementById('your_overflow_scroll_div');
    overflowScrollElement[0].scrollTop = overflowScrollElement[0].scrollHeight;

  }
]);

Просто потому, что перенос элементов jQuery по сравнению с HTML-элементами DOM немного сбивает с толку angular.

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


3

small addendum: прокручивается только, если последняя строка уже видна. если прокрутить чуть-чуть, оставляет содержимое там, где оно есть (внимание: не тестируется с разными размерами шрифта. это может потребовать некоторых настроек внутри "> = сравнения"):

var objDiv = document.getElementById(id);
var doScroll=objDiv.scrollTop>=(objDiv.scrollHeight-objDiv.clientHeight);                   

// add new content to div
$('#' + id ).append("new line at end<br>"); // this is jquery!

// doScroll is true, if we the bottom line is already visible
if( doScroll) objDiv.scrollTop = objDiv.scrollHeight;

3

Так же, как бонусный фрагмент. Я использую angular и пытался прокрутить ветку сообщений до конца, когда пользователь выбирал разные разговоры с пользователями. Чтобы убедиться, что прокрутка работает после того, как новые данные были загружены в div с ng-repeat для сообщений, просто оберните фрагмент прокрутки в тайм-аут.

$timeout(function(){
    var messageThread = document.getElementById('message-thread-div-id');
    messageThread.scrollTop = messageThread.scrollHeight;
},0)

Это обеспечит запуск события прокрутки после вставки данных в DOM.


Я подозреваю, что $ scope. $ Apply (callback) будет работать так же хорошо, как это вызывает дайджест и переоценку представления.
SStanley

Спасибо! Мне действительно было интересно, почему я не смог заставить его работать, и проблема была в $ timeout.
Wayferer

@ Wayferer жеsetTimeout(function() { ... }, n)
KingRider

3

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

$("html,body").animate({scrollTop:$("#div-id")[0].offsetTop}, 1000);

что приведет к плавной прокрутке к началу div с идентификатором "div-id".



2

Это позволит вам прокручивать всю страницу вниз по высоте документа.

$('html, body').animate({scrollTop:$(document).height()}, 1000);

1

Очень простой способ для этого - установить scroll toвысоту div.

var myDiv = document.getElementById("myDiv");
window.scrollTo(0, myDiv.innerHeight);

1

Прокрутите до последнего элемента внутри div:

myDiv.scrollTop = myDiv.lastChild.offsetTop

1

В моем приложении Angular 6 я просто сделал это:

postMessage() {
  // post functions here
  let history = document.getElementById('history')
  let interval    
  interval = setInterval(function() {
    history.scrollTop = history.scrollHeight
    clearInterval(interval)
  }, 1)
}

Функция clearInterval (интервал) остановит таймер, чтобы разрешить ручную прокрутку вверх / вниз.


1

Мой сценарий: у меня был список строк, в который мне нужно было добавить строку, заданную пользователем, и автоматически прокрутить до конца списка. Я зафиксировал высоту отображения списка, после чего он должен был переполниться.

Я попробовал ответ @ Джереми Рутена, он работал, но он переходил к (n-1) -ому элементу. Если кто-то сталкивается с такой проблемой, вы можете использовать setTimeOut()метод обхода. Вам нужно изменить код ниже:

setTimeout(() => {
    var objDiv = document.getElementById('div_id');
    objDiv.scrollTop = objDiv.scrollHeight
}, 0)

Вот ссылка на StcakBlitz, которую я создал, которая показывает проблему и ее решение: https://stackblitz.com/edit/angular-ivy-x9esw8


-1

Я знаю, что это старый вопрос, но ни одно из этих решений не сработало для меня. В итоге я использовал offset (). Top, чтобы получить желаемые результаты. Вот что я использовал, чтобы аккуратно прокрутить экран до последнего сообщения в моем приложении чата:

$("#html, body").stop().animate({
     scrollTop: $("#last-message").offset().top
}, 2000);

Я надеюсь, что это помогает кому-то еще.


-1

Иногда самое простое - это лучшее решение: я не знаю, поможет ли это, оно помогло мне прокрутить, когда я тоже хотел. Чем выше значение «y =», тем больше он прокручивается вниз и, конечно, «0» означает «верх», поэтому, например, «1000» может быть нижним, «2000» или «3000» и т. Д., В зависимости от того, как долго ваш страница есть. Это обычно работает в кнопках с onclick или onmouseover.

window.scrollTo(x=0,y=150);

-1

Установите расстояние от верхней части прокручиваемого элемента до полной высоты элемента.

const element = this.shadowRoot.getElementById('my-scrollable-div')
element.scrollTop = element.scrollHeight

Не добавляйте то же решение, если оно уже существует.
Асон

да не делай этого, если решение уже существует
Освальдо

-1

Вы можете использовать метод HTML DOM scrollIntoView следующим образом:

var element = document.getElementById("scroll");
element.scrollIntoView();

-2

использовать:

var element= $('element');
var maxScrollTop = element[0].scrollHeight - element.outerHeight();
element.scrollTop(maxScrollTop);

или проверьте прокрутку вниз:

    var element = $(element);
    var maxScrollTop = element[0].scrollHeight - element.outerHeight();
    element.on('scroll', function() {
        if ( element.scrollTop() >= maxScrollTop ) {
            alert('scroll to bottom');
        }
    });

измените scrollTopMax на var maxScrollTop = element [0] .scrollHeight - element.outerHeight ();
Махди Багери

-2

Если это делается для прокрутки до нижней части окна чата, выполните следующие действия.

Идея прокрутки до определенного div в чате была следующей

1) Каждый div чата, состоящий из Person, времени и сообщения, запускается в цикле for с классом chatContentbox

2) querySelectorAll находит все такие массивы. Это может быть 400 узлов (400 чатов)

3) перейти к последнему

4) scrollIntoView ()

let lastChatBox = document.querySelectorAll('.chatContentBox'); 
lastChatBox = lastChatBox[lastChatBox.length-1]; 
lastChatBox.scrollIntoView(); 

Несколько ответов уже дано, используя scrollIntoView, так что нет необходимости добавлять еще один.
Асон
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.