Прокрутить до нижней части div?
Я создаю чат, используя ajax-запросы в rails, и пытаюсь получить div для прокрутки до дна без особой удачи.
Я оборачиваю все в этом div:
#scroll {
height:400px;
overflow:scroll;
}
Есть ли способ сохранить прокрутку вниз по умолчанию с помощью JS?
Есть ли способ сохранить прокрутку вниз после запроса AJAX?
35 ответов
Вот что я использую на своем сайте:
var objDiv = document.getElementById("your_div");
objDiv.scrollTop = objDiv.scrollHeight;
Это намного проще, если вы используете jQuery:
$("#mydiv").scrollTop($("#mydiv")[0].scrollHeight);
Вы можете использовать следующий код:
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
Используя jQuery animate:
$('#DebugContainer').stop().animate({
scrollTop: $('#DebugContainer')[0].scrollHeight
}, 800);
альтернативное решение
function scrollToBottom(element) {
element.scroll({ top: element.scrollHeight, behavior: 'smooth' });
}
var mydiv = $("#scroll");
mydiv.scrollTop(mydiv.prop("scrollHeight"));
Работает с JQuery 1.6
плавная прокрутка с помощью Javascript:
document.getElementById('messages').scrollIntoView({ behavior: 'smooth', block: 'end' });
Если вы не хотите полагаться на scrollHeight
, следующий код помогает:
$('#scroll').scrollTop(1000000);
Мой сценарий: у меня был список строк, в который мне нужно было добавить строку, заданную пользователем, и автоматически прокрутить до конца списка. У меня была фиксированная высота отображения списка, после чего он должен переполняться.
Я попробовал ответить @Jeremy Ruten, он сработал, но прокручивался до (n-1) -го элемента. Если кто-то сталкивается с этой проблемой, вы можете использоватьsetTimeOut()
способ обходного пути. Вам необходимо изменить код, как показано ниже:
setTimeout(() => {
var objDiv = document.getElementById('div_id');
objDiv.scrollTop = objDiv.scrollHeight
}, 0)
Вот созданная мной ссылка StcakBlitz, в которой показана проблема и ее решение: https://stackblitz.com/edit/angular-ivy-x9esw8
Метод, не требующий JavaScript (2023 г.)
Вот метод, который вообще не требует никакого JavaScript и использует чистый (Flexbox) CSS. Более подробно этот метод я объяснил здесь.
Хитрость заключается в том, чтобы поместить элементы в элемент «content», который заключен внутри элемента.column-reverse
элемент flexbox, который действует как «прокрутка». Поскольку элементы находятся в другом контейнере («контент»), они не «переворачиваются», а всегда выстраиваются в линию внизу. Фактически, это заставляет скроллер прокручиваться вниз всякий раз, когда что-то добавляется.
Преимущества этого метода
Помимо отсутствия использования JavaScript, большим преимуществом этого метода является то, что, когда пользователь начинает прокручивать список, позиция прокрутки остается фиксированной до той точки, до которой пользователь прокрутил. Это предотвращает раздражающее перескакивание содержимого при добавлении новых элементов. Как только пользователь снова прокрутит страницу вниз, список останется прокрученным вниз при обновлении.
Демо
Примечание. JavaScript в приведенной ниже демонстрации требуется только для самой демонстрации (чтобы добавить элементы в список и посмотреть, что произойдет).
Если ваш проект ориентирован на современные браузеры , теперь вы можете использовать привязку прокрутки CSS для управления поведением прокрутки, например, для сохранения любого динамически созданного элемента внизу.
Java Script:
document.getElementById('messages').scrollIntoView(false);
Прокрутка до последней строки содержимого присутствует.
Вы можете использовать метод scrollIntoView HTML DOM следующим образом:
var element = document.getElementById("scroll");
element.scrollIntoView();
Javascript или JQuery:
var scroll = document.getElementById('messages');
scroll.scrollTop = scroll.scrollHeight;
scroll.animate({scrollTop: scroll.scrollHeight});
Css:
.messages
{
height: 100%;
overflow: auto;
}
Как и вы, я создаю приложение для чата и хочу, чтобы последнее сообщение отображалось в поле зрения. В конечном итоге это сработало для меня:
//get the div that contains all the messages
let div = document.getElementById('message-container');
//make the last element (a message) to scroll into view, smoothly!
div.lastElementChild.scrollIntoView({ behavior: 'smooth' });
Используя 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);
Нашел это действительно полезным, спасибо.
Для пользователей 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.
Также для приложения чата было полезно сделать это назначение после того, как ваши чаты были загружены, вам также может понадобиться короткое время ожидания.
Я столкнулся с той же проблемой, но с дополнительным ограничением: у меня не было контроля над кодом, добавляющим новые элементы в контейнер прокрутки. Ни один из приведенных здесь примеров не позволил мне сделать именно это. Вот решение, которое я выбрал.
Оно использует 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/
Это позволит вам прокрутить всю страницу вниз по высоте документа.
$('html, body').animate({scrollTop:$(document).height()}, 1000);
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;
Вы также можете, используя jQuery, прикрепить анимацию к html,body
документа через:
$("html,body").animate({scrollTop:$("#div-id")[0].offsetTop}, 1000);
что приведет к плавной прокрутке к началу div с идентификатором "div-id".
Вы можете использовать метод Element.scrollTo().
Его можно анимировать с помощью встроенной анимации браузера / ОС, так что он очень плавный.
function scrollToBottom() {
const scrollContainer = document.getElementById('container');
scrollContainer.scrollTo({
top: scrollContainer.scrollHeight,
left: 0,
behavior: 'smooth'
});
}
// initialize dummy content
const scrollContainer = document.getElementById('container');
const numCards = 100;
let contentInnerHtml = '';
for (let i=0; i<numCards; i++) {
contentInnerHtml += `<div class="card mb-2"><div class="card-body">Card ${i + 1}</div></div>`;
}
scrollContainer.innerHTML = contentInnerHtml;
.overflow-y-scroll {
overflow-y: scroll;
}
<link href="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/css/bootstrap.min.css" rel="stylesheet"/>
<div class="d-flex flex-column vh-100">
<div id="container" class="overflow-y-scroll flex-grow-1"></div>
<div>
<button class="btn btn-primary" onclick="scrollToBottom()">Scroll to bottom</button>
</div>
</div>
Почему бы не использовать для этого простой CSS?
Хитрость заключается в использовании display: flex; и flex-direction: column-reverse;
Here is a working example. https://codepen.io/jimbol/pen/YVJzBg
Так же, как бонусный фрагмент. Я использую angular и пытался прокрутить ветку сообщений до конца, когда пользователь выбирал разные разговоры с пользователями. Чтобы убедиться, что прокрутка работает после того, как новые данные были загружены в div с ng-repeat для сообщений, просто оберните фрагмент прокрутки в тайм-аут.
$timeout(function(){
var messageThread = document.getElementById('message-thread-div-id');
messageThread.scrollTop = messageThread.scrollHeight;
},0)
Это обеспечит запуск события прокрутки после вставки данных в DOM.
Только css:
.scroll-container {
overflow-anchor: none;
}
Делает так, чтобы полоса прокрутки не оставалась привязанной к вершине при добавлении дочернего элемента. Например, когда новое сообщение добавлено в нижней части чата, прокрутите чат до нового сообщения.
Прокрутите до последнего элемента внутри div:
myDiv.scrollTop = myDiv.lastChild.offsetTop
Очень простой способ это установить scroll to
на высоту див.
var myDiv = document.getElementById("myDiv");
window.scrollTo(0, myDiv.innerHeight);
В моем приложении Angular 6 я только что сделал это:
postMessage() {
// post functions here
let history = document.getElementById('history')
let interval
interval = setInterval(function() {
history.scrollTop = history.scrollHeight
clearInterval(interval)
}, 1)
}
Функция clearInterval(interval) остановит таймер, чтобы разрешить ручную прокрутку вверх / вниз.
Я использую разницу между координатой Y первого элемента div и координатой Y выбранного элемента div. Вот код JavaScript/JQuery и html:
function scrollTo(event){
// In my proof of concept, I had a few <button>s with value
// attributes containing strings with id selector expressions
// like "#item1".
let selectItem = $($(event.target).attr('value'));
let selectedDivTop = selectItem.offset().top;
let scrollingDiv = selectItem.parent();
let firstItem = scrollingDiv.children('div').first();
let firstItemTop = firstItem.offset().top;
let newScrollValue = selectedDivTop - firstItemTop;
scrollingDiv.scrollTop(newScrollValue);
}
<div id="scrolling" style="height: 2rem; overflow-y: scroll">
<div id="item1">One</div>
<div id="item2">Two</div>
<div id="item3">Three</div>
<div id="item4">Four</div>
<div id="item5">Five</div>
</div>