Продовжуйте переповнення діва прокручувати донизу, якщо користувач не прокручує вгору


224

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

Чи можливо створити div, який буде прокручуватися донизу, якщо користувач не прокручує вгору і коли користувач прокручує назад до низу, він повинен тримати себе внизу, навіть коли додається новий динамічний контент. Як би я походив, створюючи це.


1
використовуйте позицію css вгорі, тримайте її внизу {position : relative; bottom:0;}. Видаліть властивість css, коли користувач прокрутить.
TCHdvlp

оскільки ви не прийняли відповідь, я хочу запитати: це спрацювало для вас?
Містер Манхеттен

4
Звучить як чат, який ви хочете досягти
Thielicious

1
Для нового в цьому питанні слід спробувати оснастити css у 2020 році .
Венер

Відповіді:


136

Це може допомогти вам:

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

[EDIT], щоб відповідати коментарю ...

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

3
Це добре прокручує його донизу при завантаженні сторінки, але мені потрібно, щоб він залишався внизу, коли додається динамічний контент, якщо користувач не прокрутив вгору.
Роберт Е. Макінтош

12
Наскільки я можу сказати, це не вмикає динамічну прокрутку, коли користувач прокручується донизу ...
TvE

@TvE, чи не може ми додати підтримку?
Barkermn01

6
Погане рішення. Немає підстав додавати setIntervalдля цієї легкої проблеми.
етанкрист

6
@ethancrist, проте, ти не пропонуєш альтернативи ... знизує плечима.
Jarett Lloyd

180

Мені вдалося це працювати лише з CSS.

Хитрість полягає у використанні display: flex;таflex-direction: column-reverse;

Нижній переглядач розглядає дно, як його верх. Якщо припустити браузери, на які ви орієнтуєтесь на підтримку flex-box, єдиний застереження полягає в тому, що розмітка повинна бути в зворотному порядку.

Ось робочий приклад. https://codepen.io/jimbol/pen/YVJzBg


42
Ви можете подолати необхідність змінити вміст, додавши додаткову обгортку та застосувавши overflow:auto; display:flex; flex-direction:column-reverse;до зовнішньої обгортки замість внутрішньої обгортки.
Натан Артур

6
мабуть, найкраще рішення, оскільки йому не потрібен JavaScript.
Аміт Кумар Харе

3
@NathanArthur u da real mvp
php_nub_qq

13
@NathanArthur Насправді, якщо ви просто додасте div під контейнер, щоб скасувати все назад: codepen.io/anon/pen/pdrLEZ
Coo

6
На жаль, це рішення, здається, не працює у Firefox :(
Стюарт

166

Я щойно це здійснив і, можливо, ви можете використовувати мій підхід.

Скажімо, у нас є такий 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 - верх, а макс - висота елемента прокрутки, мінус сама висота елемента. Під час використання смуги прокрутки може бути важко (для мене це було в Chrome) отримати смугу прокрутки аж донизу. тому я кинув неточність в 1px. Так isScrolledToBottomбуде вірно навіть у тому випадку, якщо смуга прокрутки 1px знизу. Ви можете налаштувати це на все, що вам здається правильним.

Тоді це просто питання встановлення елемента scrollTop донизу.

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

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

EDIT: Додано фрагмент коду, щоб уточнити, коли 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>


22
Це насправді єдине рішення, що виконує поставлене питання. І повинна була бути позначена як правильна відповідь.
preezzzy

1
@dotnetCarpenter: Мені здається, що тобі потрібно if(!isScrolledToBottom): тест мені здається неправильним (і не працював у моєму коді, поки я його не виправив).
luskwater

1
@luskwater Ви можете надати fsfiddle зі своїм виправленням? Я не розумію проблеми з out.scrollHeight - out.clientHeight <= out.scrollTop + 1. Ви використовуєте прокладки у своєму CSS?
dotnetCarpenter

2
Це те, що я шукав. І це відповідь на поставлене ОП питання. Спасибі dotnetCarperter.
Луїс Мендживар

1
Якщо хтось отримує 0, коли йому дзвонять scrollTop, я пропоную використовувати, document.getScrollingElementяк тут запропоновано: stackoverflow.com/questions/36227559/scrolltop-always-returns-0/…
Дейн Джордан

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

Демо-версія: http://jsfiddle.net/KGfG2/


4
Це добре прокручує його донизу при завантаженні сторінки, але мені потрібно, щоб він залишався внизу, коли додається динамічний контент, якщо користувач не прокрутив вгору.
Роберт Е. Макінтош

Це прекрасно працює. Я оновлюю динамічний контент, і прокрутка завжди внизу.
Енді Байка

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

Or animated:

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

1
Це добре прокручує його донизу при завантаженні сторінки, але мені потрібно, щоб він залишався внизу, коли додається динамічний контент, якщо користувач не прокрутив вгору.
Роберт Е. Макінтош

Це не спрацьовує, коли діва сильно зростає на першому знімку. наприклад, у Angular-js, react js, завантаженні шаблону Meteor Blaze, це не буде працювати.
Анкур Соні

Це працювало для мене. Я думаю, що це прекрасно спрацьовує, якщо відповідний дів буде залишатися незмінним. Не перевірив його з динамічними висотами.
doij790

11

У 2020 році ви можете використовувати css snap , але перед тим, як Chrome 81 змінити макет не призведе до повторного оснащення , чистий CSS чат працює у Chrome 81, також ви можете перевірити Чи можна використовувати CSS оснащення .

Ця демонстрація оснастить останній елемент, якщо його видно, прокрутіть донизу, щоб побачити ефект.

.container {
  overflow-y: scroll;
  overscroll-behavior-y: contain;
  scroll-snap-type: y mandatory;
}

.container > div > div:last-child {
  scroll-snap-align: end;
}

.container > div > div {
  background: lightgray;
  height: 3rem;
  font-size: 1.5rem;
}
.container > div > div:nth-child(2n) {
  background: gray;
}
<div class="container" style="height:6rem">
<div>
<div>1</div>
<div>2</div>
<div>3</div>
<div>4</div>
<div>5</div>
</div>
</div>

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


5

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

  1. Run code snippetщоб побачити ефект. (PS: Якщо Run code snippetце не працює, спробуйте це: https://jsfiddle.net/Yeshen/xm2yLksu/3/ )

  2. Як це працює:

Переповнення за замовчуванням прокручується зверху вниз.

transform: rotate(180deg) може змусити його прокручувати або завантажувати динамічний блок знизу вгору.

  1. Оригінальна ідея:

https://blog.csdn.net/yeshennet/article/details/88880252


Будь ласка, додайте більше пояснень, як ваш код вирішує питання ОП
jro

1, додав додатковий вступ. 2, Будь ласка Run code snippet, безпосередньо дивіться ефект.
yisheng wu

Кнопка фрагмента запуску коду для мене не з’являється. Перевірте своє форматування
jro

Це чудово. Будь ласка , включите посилання у відповідь
JRO

2
Дуже креативне рішення. Однак це повертає нормальну роботу колеса прокрутки моєї миші. Щоб піднятися вгору, я повинен прокручувати "вниз" і навпаки.
mfluehr

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

Це обчислить позицію ScrollTop з висоти #yourDivIDвикористання $(document).height()властивості, так що навіть якщо динамічний вміст буде додано до діва, скроллер завжди буде знаходитись у нижньому положенні. Сподіваюсь, це допомагає. Але у нього також є невелика помилка, навіть якщо ми прокручуємо вгору і залишаємо вказівник миші зі скроллера, він автоматично перейде в нижнє положення. Якщо хтось може виправити, це теж буде добре.


2
//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 та chrome ..


2

Відповідь Джима Холла є кращою, оскільки, хоча вона справді не прокручується донизу, коли ви прокручуєте вгору, це також чистий CSS.

Але, на жаль, це не є стабільним рішенням: У Chrome (можливо, через проблему 1-px, описану dotnetCarpenter вище), scrollTopповодиться неточно на 1 піксель, навіть без взаємодії з користувачем (при додаванні елемента). Ви можете встановитиscrollTop = scrollHeight - clientHeight , але це дозволить утримати діву в положенні, коли буде доданий ще один елемент, він же функція "тримати себе внизу".

Отже, коротко кажучи, додавання невеликої кількості Javascript (зітхання) виправить це та виконає всі вимоги:

Щось на зразок https://codepen.io/anon/pen/pdrLEZ це (наприклад, Coo), а після додавання елемента до списку також:

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

де 29 - висота однієї лінії.

Отже, коли користувач прокручує вгору пів рядка (якщо це навіть можливо?), Javascript проігнорує його і прокрутить донизу. Але я гадаю, що це нехтувати. І він виправляє Chrome 1 px штуку.


2

Ось рішення, засноване на публікації в блозі Райана Ханта . Це залежить від overflow-anchorвластивості CSS, яка прив'язує позицію прокрутки до елемента внизу вмісту прокрутки.

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>

Зауважте, що overflow-anchorнаразі це не працює в Safari чи Edge, тому це рішення наразі працює не у всіх браузерах.


1

Ви можете використовувати щось подібне,

var element = document.getElementById("yourDivID");
window.scrollTo(0,element.offsetHeight);

Поясніть це будь ласка!
Szabolcs Páll

1.scrollTo - це метод, який прокручує все вікно до конкретних координат.2.offsetHeight дасть висоту вашого елемента, тому другий рядок наведеного вище коду продовжує прокручувати вікно вниз, поки ви щось призначаєте.
Яшеш Чаухан

0

Ось як я підійшов до цього. Мій зріст - 650 пікс. Я вирішив, що якщо висота прокрутки знаходиться в межах 150 пікселів від нижньої, то автоматично прокрутіть її. Інше, залиште це для користувача.

if (container_block.scrollHeight - container_block.scrollTop < 800) {
                    container_block.scrollTo(0, container_block.scrollHeight);
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.