Держите переполненный div прокрученным вниз, если пользователь не прокрутит вверх

У меня есть div, размер которого составляет всего 300 пикселей, и я хочу, чтобы страница загружалась в нижнюю часть содержимого. Этот div имеет динамически добавленный контент и должен оставаться прокрученным до конца. Теперь, если пользователь решает прокрутить вверх, я не хочу, чтобы он возвращался назад, пока пользователь снова не прокручивается вниз.

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

Ответ 1

Это может помочь вам:

var element = document.getElementById("yourDivID");
element.scrollTop = element.scrollHeight;

[РЕДАКТИРОВАТЬ], чтобы соответствовать комментарию...

function updateScroll(){
    var element = document.getElementById("yourDivID");
    element.scrollTop = element.scrollHeight;
}

при каждом добавлении контента вызывайте функцию updateScroll() или устанавливайте таймер:

//once a second
setInterval(updateScroll,1000);

если вы хотите обновить ТОЛЬКО если пользователь не двигался:

var scrolled = false;
function updateScroll(){
    if(!scrolled){
        var element = document.getElementById("yourDivID");
        element.scrollTop = element.scrollHeight;
    }
}

$("#yourDivID").on('scroll', function(){
    scrolled=true;
});

Ответ 2

Я только что реализовал это, и, возможно, вы можете использовать мой подход.

Скажем, у нас есть следующий HTML:

<div id="out" style="overflow:auto"></div>

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

var out = document.getElementById("out");
// allow 1px inaccuracy by adding 1
var isScrolledToBottom = out.scrollHeight - out.clientHeight <= out.scrollTop + 1;

scrollHeight дает вам высоту элемента, включая любую невидимую область из-за переполнения. clientHeight дает вам высоту CSS или, иначе говоря, фактическую высоту элемента. Оба метода возвращают высоту без margin, поэтому вам не нужно об этом беспокоиться. scrollTop дает вам положение вертикальной прокрутки. 0 - это верх, а max - это scrollHeight элемента за вычетом самой высоты элемента. При использовании полосы прокрутки может быть трудно (это было в Chrome для меня), чтобы получить полосу прокрутки до самого дна. поэтому я добавил неточность в 1 пиксель. Таким образом, isScrolledToBottom будет иметь значение true, даже если полоса прокрутки расположена на 1 пиксель снизу. Вы можете установить это так, как считаете нужным.

Тогда это просто вопрос установки scrollTop элемента внизу.

if(isScrolledToBottom)
    out.scrollTop = out.scrollHeight - out.clientHeight;

Я сделал для вас скрипку, чтобы показать концепцию: http://jsfiddle.net/dotnetCarpenter/KpM5j/

РЕДАКТИРОВАТЬ: Добавлен фрагмент кода, чтобы уточнить, когда isScrolledToBottom имеет значение true.

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

const out = document.getElementById("out")
let c = 0

setInterval(function() {
    // allow 1px inaccuracy by adding 1
    const isScrolledToBottom = out.scrollHeight - out.clientHeight <= out.scrollTop + 1

    const newElement = document.createElement("div")

    newElement.textContent = format(c++, 'Bottom position:', out.scrollHeight - out.clientHeight,  'Scroll position:', out.scrollTop)

    out.appendChild(newElement)

    // scroll to bottom if isScrolledToBottom is true
    if (isScrolledToBottom) {
      out.scrollTop = out.scrollHeight - out.clientHeight
    }
}, 500)

function format () {
  return Array.prototype.slice.call(arguments).join(' ')
}
#out {
    height: 100px;
}
<div id="out" style="overflow:auto"></div>
<p>To be clear: We want the scrollbar to stick to the bottom if we have scrolled all the way down. If we scroll up, then we don't want the content to move.
</p>

Ответ 3

Мне удалось получить эту работу только с CSS.

Трюк заключается в использовании display: flex; и flex-direction: column-reverse;

Браузер рассматривает нижнюю часть как верхнюю. Предполагая, что браузеры, на которые вы нацеливаете поддержку flex-box, единственное предостережение в том, что разметка должна быть в обратном порядке.

Вот рабочий пример. https://codepen.io/jimbol/pen/YVJzBg

Ответ 4

$('#yourDiv').scrollTop($('#yourDiv')[0].scrollHeight);

Живая демоверсия: http://jsfiddle.net/KGfG2/

Ответ 5

$('#div1').scrollTop($('#div1')[0].scrollHeight);

Or animated:

$("#div1").animate({ scrollTop: $('#div1')[0].scrollHeight}, 1000);

Ответ 6

$('#yourDivID').animate({ scrollTop: $(document).height() }, "slow");
return false;

Это вычислит позицию ScrollTop из высоты #yourDivID с использованием #yourDivID $(document).height() так что даже если динамическое содержимое добавлено в div, скроллер всегда будет в нижней позиции. Надеюсь это поможет. Но он также имеет небольшую ошибку, даже если мы прокручиваем вверх и оставляем указатель мыши на скроллере, он автоматически перейдет в нижнюю позицию. Если кто-то сможет это исправить, это тоже будет хорошо.

Ответ 7

.cont{
height: 100px;
overflow-x: hidden;
overflow-y: auto;
transform: rotate(180deg);
direction:rtl;
text-align:left;
}
ul{
overflow: hidden;
transform: rotate(180deg);
}
<div class="cont"> 
 <ul>
   <li>0</li>
   <li>1</li>
   <li>2</li>
   <li>3</li>
   <li>4</li>
   <li>5</li>
   <li>6</li>
   <li>7</li>
   <li>8</li>
   <li>9</li>
   <li>10</li>  
 </ul>
</div>

Ответ 8

//Make sure message list is scrolled to the bottom
var container = $('#MessageWindowContent')[0];
var containerHeight = container.clientHeight;
var contentHeight = container.scrollHeight;

container.scrollTop = contentHeight - containerHeight;

Вот моя версия, основанная на ответе dotnetCarpenter. Мой подход - это чистый jQuery, и я назвал переменные, чтобы сделать вещи немного понятнее. Что происходит, если высота содержимого больше, чем контейнер, мы прокручиваем дополнительное расстояние до достижения желаемого результата.

Работает в IE и хроме.

Ответ 9

Ответ Джима Холла предпочтительнее, потому что, хотя при прокрутке он действительно не прокручивается до самого дна, он также является чистым CSS.

Однако, к сожалению, это нестабильное решение: в chrome (возможно, из-за проблемы 1-px, описанной dotnetCarpenter выше), scrollTop ведет себя неточно на 1 пиксель, даже без взаимодействия с пользователем (при добавлении элемента). Вы можете установить scrollTop = scrollHeight - clientHeight, но это будет держать div в положении, когда добавляется другой элемент, иначе функция "держать себя внизу" больше не работает.

Короче говоря, добавление небольшого количества Javascript (вздоха) исправит это и выполнит все требования:

Что-то вроде https://codepen.io/anon/pen/pdrLEZ this (например, Coo), и после добавления элемента в список также следующее:

container = ...
if(container.scrollHeight - container.clientHeight - container.scrollTop <= 29) {
    container.scrollTop = container.scrollHeight - container.clientHeight;
}

где 29 - высота одной строки.

Таким образом, когда пользователь прокручивает на половину строки вверх (если это вообще возможно?), Javascript игнорирует его и прокручивает до конца. Но я думаю, что это пренебрежимо мало. И это исправляет Chrome 1 px вещь.

Ответ 10

Вот решение, основанное на сообщении в блоге Райана Ханта. Это зависит от CSS-свойства overflow-anchor, которое overflow-anchor позицию прокрутки к элементу в нижней части прокручиваемого содержимого.

const messages = [
  'Expect rain today.',
  'Tomorrow will be sunny.',
  'Snow is coming next week.',
  'Hailstorms are imminent.',
];

function addMessage() {
  const $message = document.createElement('div');
  $message.className = 'message';
  $message.innerText = messages[(Math.random() * messages.length) | 0];
  $messages.insertBefore($message, $anchor);

  // Trigger the scroll pinning when the scroller overflows
  if (!overflowing) {
    overflowing = isOverflowing($scroller);
    $scroller.scrollTop = $scroller.scrollHeight;
  }
}

function isOverflowing($el) {
  return $el.scrollHeight > $el.clientHeight;
}

const $scroller = document.querySelector('.scroller');
const $messages = document.querySelector('.messages');
const $anchor = document.querySelector('.anchor');
let overflowing = false;

setInterval(addMessage, 1000);
.scroller {
  overflow: auto;
  height: 90vh;
  max-height: 11em;
  background: #555;
}

.messages > * {
  overflow-anchor: none;
}

.anchor {
  overflow-anchor: auto;
  height: 1px;
}

.message {
  margin: .3em;
  padding: .5em;
  background: #eee;
}
<section class="scroller">
  <div class="messages">
    <div class="anchor"></div>
  </div>
</section>

Ответ 11

Вот как я подошел к этому. Мой рост div составляет 650 пикселей. Я решил, что если высота прокрутки находится в пределах 150px от нижней части, то автоматически прокручиваю ее. Иначе, оставьте это для пользователя.

if (container_block.scrollHeight - container_block.scrollTop < 800) {
                    container_block.scrollTo(0, container_block.scrollHeight);
}