Simpan div overflow yang digulir ke bawah kecuali pengguna menggulir ke atas

223

Saya memiliki div yang hanya 300 piksel besar dan saya ingin ketika halaman memuat gulir ke bagian bawah konten. Div ini memiliki konten yang ditambahkan secara dinamis ke dalamnya dan harus tetap digulir sepenuhnya. Sekarang jika pengguna memutuskan untuk menggulir ke atas, saya tidak ingin itu melompat kembali ke bawah sampai pengguna menggulir ke bawah lagi

Apakah mungkin untuk memiliki div yang akan tetap digulir ke bawah kecuali jika pengguna menggulir ke atas dan ketika pengguna menggulir kembali ke bawah itu perlu menjaga dirinya di bagian bawah bahkan ketika konten dinamis baru ditambahkan. Bagaimana cara saya membuat ini.

Robert E. McIntosh
sumber
1
gunakan posisi css atas tetap di bawah {position : relative; bottom:0;}. Hapus properti css setelah pengguna memiliki gulir.
TCHdvlp
karena Anda tidak menerima jawaban, saya ingin bertanya: apakah itu berhasil untuk Anda?
Mr.Manhattan
4
Kedengarannya seperti kotak obrolan yang ingin Anda capai
Thielicious
1
Untuk pertanyaan baru ini, sebaiknya coba css snap pada tahun 2020 .
mulai

Jawaban:

136

Ini mungkin membantu Anda:

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

[EDIT], untuk mencocokkan komentar ...

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

setiap kali konten ditambahkan, panggil fungsi updateScroll (), atau atur timer:

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

jika Anda ingin memperbarui HANYA jika pengguna tidak bergerak:

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

$("#yourDivID").on('scroll', function(){
    scrolled=true;
});
Mr.Manhattan
sumber
3
Sumur ini gulir ke bawah pada pemuatan halaman, tetapi saya perlu untuk tetap di bagian bawah ketika konten dinamis ditambahkan kecuali pengguna telah menggulir ke atas.
Robert E. McIntosh
12
Sejauh yang saya tahu ini tidak mengaktifkan kembali pengguliran dinamis ketika pengguna menggulir kembali ke bawah ...
TvE
@TvE tidak bisakah kita dukungan itu ditambahkan?
Barkermn01
6
Solusi buruk Tidak ada alasan untuk menambahkan setIntervalmasalah ringan ini.
etancrist
6
@etancrist Namun, Anda tidak menawarkan alternatif ... mengangkat bahu.
Jarett Lloyd
180

Saya bisa menjalankan ini dengan CSS saja.

Caranya adalah dengan menggunakan display: flex;danflex-direction: column-reverse;

Browser memperlakukan bagian bawah seperti bagian atas. Dengan asumsi browser yang Anda targetkan mendukung flex-box, satu-satunya peringatan adalah bahwa markup harus dalam urutan terbalik.

Berikut ini contoh kerjanya. https://codepen.io/jimbol/pen/YVJzBg

Jim Hall
sumber
42
Anda dapat berkeliling untuk membalikkan konten dengan menambahkan pembungkus tambahan, dan menerapkannya overflow:auto; display:flex; flex-direction:column-reverse;ke pembungkus luar alih-alih pembungkus dalam.
Nathan Arthur
6
mungkin solusi terbaik karena tidak perlu javascript.
Amit Kumar Khare
3
@NathanArthur u da real mvp
php_nub_qq
13
@NathanArthur Bahkan, jika Anda hanya menambahkan div di bawah wadah untuk membatalkan semuanya: codepen.io/anon/pen/pdrLEZ
Coo
6
Sayangnya solusi ini sepertinya tidak berfungsi di Firefox :(
Stuart
166

Saya baru saja mengimplementasikan ini dan mungkin Anda dapat menggunakan pendekatan saya.

Katakanlah kita memiliki HTML berikut:

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

Kemudian kita dapat memeriksa apakah itu digulir ke bawah dengan:

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

scrollHeight memberi Anda ketinggian elemen, termasuk area yang tidak terlihat karena meluap. clientHeight memberi Anda ketinggian CSS atau berkata dengan cara lain, ketinggian elemen yang sebenarnya. Kedua metode mengembalikan ketinggian tanpa margin, jadi Anda tidak perlu khawatir tentang itu. scrollTop memberi Anda posisi gulir vertikal. 0 adalah top dan max adalah scrollHeight dari elemen minus tinggi elemen itu sendiri. Saat menggunakan bilah gulir itu bisa sulit (itu di Chrome bagi saya) untuk mendapatkan bilah gulir sampai ke bawah. jadi saya melempar 1px ketidaktepatan. Jadi isScrolledToBottomakan benar bahkan jika bilah gulir adalah 1px dari bawah. Anda dapat mengatur ini untuk apa pun yang terasa benar bagi Anda.

Maka itu hanya masalah pengaturan scrollTop elemen ke bawah.

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

Saya telah membuat biola bagi Anda untuk menunjukkan konsep: http://jsfiddle.net/dotnetCarpenter/KpM5j/

EDIT: Ditambahkan potongan kode untuk memperjelas saat isScrolledToBottomini true.

Tempel bilah gulir ke bawah

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>

dotnetCarpenter
sumber
22
Ini sebenarnya satu-satunya solusi yang menyelesaikan pertanyaan yang dinyatakan. Dan seharusnya sudah ditandai sebagai jawaban yang benar.
preezzzy
1
@dotnetCarpenter: Tampaknya bagi saya seolah-olah Anda perlu if(!isScrolledToBottom): tes terlihat salah bagi saya (dan tidak berfungsi dalam kode saya sampai saya memperbaikinya).
luskwater
1
@luskwater, bisakah kamu menyediakan fsfiddle dengan perbaikanmu? Saya tidak mengerti masalah dengan out.scrollHeight - out.clientHeight <= out.scrollTop + 1. Apakah Anda menggunakan padding di CSS Anda?
dotnetCarpenter
2
Ini yang saya cari. Dan, ini adalah jawaban untuk pertanyaan yang diajukan OP. Terima kasih dotnetCarperter.
Luis Menjivar
1
Jika ada yang mendapatkan 0 ketika mereka memanggil scrollTop, saya sarankan menggunakan document.getScrollingElementseperti yang disarankan di sini: stackoverflow.com/questions/36227559/scrolltop-always-returns-0/…
Dane Jordan
29
$('#yourDiv').scrollTop($('#yourDiv')[0].scrollHeight);

Demo langsung: http://jsfiddle.net/KGfG2/

Alvaro
sumber
4
Sumur ini gulir ke bawah pada pemuatan halaman, tetapi saya perlu untuk tetap di bagian bawah ketika konten dinamis ditambahkan kecuali pengguna telah menggulir ke atas.
Robert E. McIntosh
Ini bekerja dengan sempurna. Saya memperbarui dengan konten dinamis dan gulir selalu di bagian bawah.
Andy Bajka
14
$('#div1').scrollTop($('#div1')[0].scrollHeight);

Or animated:

$("#div1").animate({ scrollTop: $('#div1')[0].scrollHeight}, 1000);
Sasidharan
sumber
1
Sumur ini gulir ke bawah pada pemuatan halaman, tetapi saya perlu untuk tetap di bagian bawah ketika konten dinamis ditambahkan kecuali pengguna telah menggulir ke atas.
Robert E. McIntosh
Ini tidak berfungsi ketika div tumbuh banyak di tembakan pertama. misalnya dalam Angular-js, reaksi js, pemuatan template Meteor Blaze, ini tidak akan berfungsi.
Ankur Soni
Ini berhasil untuk saya. Saya pikir itu berfungsi dengan baik jika div tersebut akan tetap tinggi secara konsisten. Belum mengujinya dengan ketinggian dinamis.
doij790
11

Pada tahun 2020, Anda dapat menggunakan css snap , tetapi sebelum Chrome 81 perubahan tata letak tidak akan memicu re-snap , chat css murni ui berfungsi di Chrome 81, Anda juga dapat memeriksa Dapatkah saya menggunakan CSS snap .

Demo ini akan mengambil elemen terakhir jika terlihat, gulir ke bawah untuk melihat efeknya.

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

masukkan deskripsi gambar di sini

Wener
sumber
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 snippetuntuk melihat efeknya. (PS: Jika Run code snippettidak berfungsi, coba ini: https://jsfiddle.net/Yeshen/xm2yLksu/3/ )

  2. Bagaimana cara kerjanya:

Overflow default adalah gulir dari atas ke bawah.

transform: rotate(180deg) dapat membuatnya gulir atau memuat blok dinamis dari bawah ke atas.

  1. Ide asli:

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

yisheng wu
sumber
Silakan tambahkan lebih banyak penjelasan tentang bagaimana kode Anda memecahkan pertanyaan OP
jro
1, telah menambahkan pengantar tambahan. 2, Tolong Run code snippet, langsung lihat efeknya.
yisheng wu
Tombol snipet kode run tidak muncul untuk saya. Periksa pemformatan Anda
1919
Itu hebat. Harap sertakan tautan dalam jawaban Anda
jro
2
Solusi yang sangat kreatif. Namun, itu membalikkan operasi normal roda gulir mouse saya. Untuk naik, saya harus menggulir "ke bawah," dan sebaliknya.
mfluehr
3
$('#yourDivID').animate({ scrollTop: $(document).height() }, "slow");
return false;

Ini akan menghitung Posisi ScrollTop dari ketinggian #yourDivIDmenggunakan $(document).height()properti sehingga bahkan jika konten dinamis ditambahkan ke div scroller akan selalu berada di posisi bawah. Semoga ini membantu. Tetapi ia juga memiliki bug kecil bahkan jika kita gulir ke atas dan meninggalkan pointer mouse dari penggulung itu secara otomatis akan datang ke posisi bawah. Jika seseorang dapat memperbaikinya juga akan menyenangkan.

Krishnadas PC
sumber
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;

Ini versi saya berdasarkan jawaban dotnetCarpenter. Pendekatan saya adalah jQuery murni dan saya menamai variabel untuk membuat hal-hal sedikit lebih jelas .. Apa yang terjadi adalah jika tinggi konten lebih besar maka wadah kita gulir jarak ekstra ke bawah untuk mencapai hasil yang diinginkan.

Bekerja di IE dan chrome ..

KingOfDaNorth
sumber
2

Jawaban Jim Hall lebih disukai karena walaupun memang tidak menggulir ke bawah ketika Anda digulir ke atas, itu juga CSS murni.

Sayangnya, ini bukan solusi yang stabil: Di chrome (mungkin karena masalah 1-px yang dijelaskan oleh dotnetCarpenter di atas), scrollTopberperilaku tidak akurat dengan 1 piksel, bahkan tanpa interaksi pengguna (pada penambahan elemen). Anda dapat mengatur scrollTop = scrollHeight - clientHeight, tetapi itu akan membuat div tetap di posisinya ketika elemen lain ditambahkan, alias fitur "keep yourself at bottom" tidak berfungsi lagi.

Jadi, singkatnya, menambahkan sejumlah kecil Javascript (mendesah) akan memperbaikinya dan memenuhi semua persyaratan:

Sesuatu seperti https://codepen.io/anon/pen/pdrLEZ ini (contoh oleh Coo), dan setelah menambahkan elemen ke daftar, juga berikut ini:

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

di mana 29 adalah ketinggian satu baris.

Jadi, ketika pengguna menggulir ke atas setengah baris (jika itu mungkin?), Javascript akan mengabaikannya dan gulir ke bawah. Tapi saya kira ini bisa diabaikan. Dan, itu memperbaiki Chrome 1 px thingy.

phil294
sumber
2

Berikut ini solusinya berdasarkan pada posting blog oleh Ryan Hunt . Itu tergantung pada overflow-anchorproperti CSS, yang menyematkan posisi gulir ke elemen di bagian bawah konten yang digulir.

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>

Perhatikan bahwa overflow-anchorsaat ini tidak berfungsi di Safari atau Edge, jadi solusi ini saat ini tidak berfungsi di semua browser.

mfluehr
sumber
1

Anda dapat menggunakan sesuatu seperti ini,

var element = document.getElementById("yourDivID");
window.scrollTo(0,element.offsetHeight);
Yashesh Chauhan
sumber
Tolong jelaskan!
Szabolcs Páll
1.scrollTo adalah metode yang menggulir seluruh jendela ke koordinat tertentu.2.offsetHeight akan memberikan ketinggian elemen Anda sehingga baris kedua kode di atas terus menggulir jendela ke bawah saat Anda menetapkan sesuatu.
Yashesh Chauhan
0

Inilah cara saya mendekatinya. Tinggi div saya adalah 650px. Saya memutuskan bahwa jika ketinggian gulir berada dalam 150px dari bawah maka gulir otomatis. Lain, tinggalkan untuk pengguna.

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