Giữ div div tràn xuống dưới trừ khi người dùng cuộn lên


222

Tôi có một div chỉ lớn 300 pixel và tôi muốn nó khi trang tải cuộn xuống cuối nội dung. Div này có nội dung được thêm động vào nó và cần phải cuộn xuống hết cỡ. Bây giờ nếu người dùng quyết định cuộn lên, tôi không muốn nó nhảy xuống phía dưới cho đến khi người dùng cuộn xuống một lần nữa

Có thể có một div sẽ được cuộn xuống phía dưới trừ khi người dùng cuộn lên và khi người dùng cuộn xuống phía dưới, nó cần giữ chính nó ở phía dưới ngay cả khi nội dung động mới được thêm vào. Làm thế nào tôi sẽ đi ra khỏi tạo ra này.


1
sử dụng vị trí css trên cùng giữ nó ở phía dưới {position : relative; bottom:0;}. Xóa thuộc tính css khi người dùng đã cuộn.
TCHvlp

vì bạn không chấp nhận câu trả lời, tôi muốn hỏi: nó có hiệu quả với bạn không?
Mr.Manhattan

4
Âm thanh giống như một hộp trò chuyện bạn muốn thực hiện
Thielicy

1
Đối với người mới cho câu hỏi này, nên thử css snap vào năm 2020 .
ngày

Câu trả lời:


136

Điều này có thể giúp bạn:

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

[EDIT], để phù hợp với nhận xét ...

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

Bất cứ khi nào nội dung được thêm vào, hãy gọi hàm updateScroll () hoặc đặt bộ hẹn giờ:

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

nếu bạn muốn cập nhật CHỈ nếu người dùng không di chuyển:

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

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

3
Điều này cũng cuộn nó xuống dưới cùng khi tải trang, nhưng tôi cần nó ở dưới cùng khi nội dung động được thêm vào trừ khi người dùng đã cuộn lên.
Robert E. McIntosh

12
Theo như tôi có thể nói điều này không kích hoạt lại cuộn động khi người dùng cuộn xuống phía dưới ...
TvE

@TvE chúng tôi không thể hỗ trợ thêm?
Barkermn01

6
Giải pháp xấu. Không có lý do để thêm setIntervalmột vấn đề nhẹ này.
đạo đức học

6
@ethancrist tuy nhiên, bạn không cung cấp thay thế ... nhún vai.
Jarett Lloyd

180

Tôi chỉ có thể làm việc này với CSS.

Bí quyết là sử dụng display: flex;flex-direction: column-reverse;

Trình duyệt xử lý phần dưới giống như phần trên của nó. Giả sử các trình duyệt bạn đang nhắm mục tiêu hỗ trợ flex-box, điều đáng chú ý duy nhất là việc đánh dấu phải theo thứ tự ngược lại.

Dưới đây là một ví dụ làm việc. https://codepen.io/jimbol/pen/YVJzBg


42
Bạn có thể nhận được xung quanh cần phải đảo ngược nội dung bằng cách thêm một trình bao bọc bổ sung và áp dụng overflow:auto; display:flex; flex-direction:column-reverse;cho trình bao bọc bên ngoài thay vì trình bao bọc bên trong.
Nathan Arthur

6
có lẽ là giải pháp tốt nhất vì nó không cần javascript.
Amit Kumar Khare

3
@NathanArthur u da real
mvp

13
@NathanArthur Trên thực tế, nếu bạn chỉ cần thêm một div dưới container để đảo ngược mọi thứ: codepen.io/anon/pen/pdrLEZ
Coo

6
Thật không may, giải pháp này dường như không hoạt động trong Firefox :(
Stuart

166

Tôi chỉ thực hiện điều này và có lẽ bạn có thể sử dụng phương pháp của tôi.

Giả sử chúng tôi có HTML sau:

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

Sau đó, chúng tôi có thể kiểm tra nếu nó cuộn xuống dưới cùng với:

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

scrollHeight cung cấp cho bạn chiều cao của phần tử, bao gồm mọi vùng không nhìn thấy do tràn. clientHeight cung cấp cho bạn chiều cao CSS hoặc nói theo một cách khác, chiều cao thực tế của phần tử. Cả hai phương pháp đều trả về chiều cao mà không cần margin, vì vậy bạn không cần phải lo lắng về điều đó. scrollTop cung cấp cho bạn vị trí của cuộn dọc. 0 là trên cùng và tối đa là cuộnHeight của phần tử trừ đi chiều cao của phần tử. Khi sử dụng thanh cuộn, có thể rất khó (trong Chrome đối với tôi) để đưa thanh cuộn xuống tận đáy. Vì vậy, tôi đã ném không chính xác 1px. Vì vậy, isScrolledToBottomsẽ đúng ngay cả khi thanh cuộn cách đáy 1px. Bạn có thể thiết lập điều này cho bất cứ điều gì cảm thấy đúng với bạn.

Sau đó, nó chỉ đơn giản là vấn đề đặt scrollTop của phần tử xuống dưới cùng.

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

Tôi đã tạo một câu đố để bạn thể hiện khái niệm: http://jsfiddle.net/dotnetCarpenter/KpM5j/

EDIT: nhập đoạn mã để làm rõ khi isScrolledToBottomtrue.

Dán thanh cuộn xuống dưới

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
Đây thực sự là giải pháp duy nhất thực hiện được câu hỏi đã nêu. Và nên được đánh dấu là câu trả lời chính xác.
preezzzy

1
@dotnetCarpenter: Đối với tôi như thể bạn cần if(!isScrolledToBottom): thử nghiệm có vẻ sai đối với tôi (và không hoạt động trong mã của tôi cho đến khi tôi sửa nó).
luskwater

1
@luskwater bạn có thể cung cấp một fsfiddle với bản sửa lỗi của bạn không? Tôi không hiểu vấn đề với out.scrollHeight - out.clientHeight <= out.scrollTop + 1. Bạn đang sử dụng phần đệm trong CSS của bạn?
dotnetCarpenter

2
Đây là những gì tôi đang tìm kiếm. Và, đây là câu trả lời cho câu hỏi OP đã hỏi. Cảm ơn dotnetCarperter.
Luis Menjivar

1
Nếu bất cứ ai là nhận được 0 khi họ gọi scrollTop, tôi đề nghị sử dụng document.getScrollingElementnhư đề xuất ở đây: stackoverflow.com/questions/36227559/scrolltop-always-returns-0/...
Dane Jordan

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

Bản demo trực tiếp: http://jsfiddle.net/KGfG2/


4
Điều này cũng cuộn nó xuống dưới cùng khi tải trang, nhưng tôi cần nó ở dưới cùng khi nội dung động được thêm vào trừ khi người dùng đã cuộn lên.
Robert E. McIntosh

Điều này hoạt động hoàn hảo. Tôi đang cập nhật với nội dung động và cuộn luôn ở phía dưới.
Andy Bajka

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

Or animated:

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

1
Điều này cũng cuộn nó xuống dưới cùng khi tải trang, nhưng tôi cần nó ở dưới cùng khi nội dung động được thêm vào trừ khi người dùng đã cuộn lên.
Robert E. McIntosh

Điều này không hoạt động khi div phát triển rất nhiều trong lần chụp đầu tiên. ví dụ: trong Angular-js, phản ứng js, tải mẫu Blaze, điều này sẽ không hoạt động.
Ankur Soni

Điều này làm việc cho tôi. Tôi nghĩ rằng nó hoạt động tốt nếu div trong câu hỏi sẽ giữ một chiều cao phù hợp. Không thử nghiệm nó với chiều cao năng động.
doij790

10

Vào năm 2020, bạn có thể sử dụng css snap , nhưng trước Chrome 81, thay đổi bố cục sẽ không kích hoạt snap-snap , một trò chuyện css thuần ui hoạt động trên Chrome 81, bạn cũng có thể kiểm tra Tôi có thể sử dụng CSS snap không .

Bản demo này sẽ chụp phần tử cuối cùng nếu nhìn thấy, cuộn xuống dưới để xem hiệu ứng.

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

nhập mô tả hình ảnh ở đây


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để thấy hiệu quả (PS: Nếu Run code snippetkhông hoạt động, hãy thử điều này: https://jsfiddle.net/Yeshen/xm2yLksu/3/ )

  2. Cách thức hoạt động:

Tràn mặc định là cuộn từ trên xuống dưới.

transform: rotate(180deg) có thể làm cho nó cuộn hoặc tải khối động từ dưới lên trên.

  1. Ý tưởng ban đầu:

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


Vui lòng thêm lời giải thích thêm về cách phá được mã của bạn câu hỏi của OP
JRO

1, đã thêm một giới thiệu bổ sung. 2, Xin vui lòng Run code snippet, trực tiếp thấy hiệu quả.
yisheng wu

Nút đoạn mã chạy không xuất hiện cho tôi. Kiểm tra định dạng của bạn
JRO

Thật tuyệt. Hãy đưa liên kết trong câu trả lời của bạn
JRO

2
Giải pháp rất sáng tạo. Tuy nhiên, nó đảo ngược hoạt động bình thường của bánh xe cuộn chuột của tôi. Để đi lên, tôi phải cuộn "xuống" và ngược lại.
mfluehr

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

Điều này sẽ tính toán Vị trí ScrollTop từ độ cao của #yourDivIDviệc sử dụng thuộc $(document).height()tính để ngay cả khi nội dung động được thêm vào div, bộ cuộn sẽ luôn ở vị trí dưới cùng. Hi vọng điêu nay co ich. Nhưng nó cũng có một lỗi nhỏ ngay cả khi chúng ta cuộn lên và rời khỏi con trỏ chuột từ thanh cuộn, nó sẽ tự động đến vị trí dưới cùng. Nếu ai đó có thể sửa nó cũng sẽ tốt đẹp.


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;

Đây là phiên bản của tôi dựa trên câu trả lời của dotnetCarpenter. Cách tiếp cận của tôi là một jQuery thuần túy và tôi đã đặt tên cho các biến để làm cho mọi thứ rõ ràng hơn một chút .. Điều gì đang xảy ra là nếu chiều cao nội dung lớn hơn thì thùng chứa chúng tôi cuộn khoảng cách thêm xuống để đạt được kết quả mong muốn.

Hoạt động trong IE và chrome ..


2

Câu trả lời của Jim Hall là thích hợp hơn bởi vì trong khi nó thực sự không cuộn xuống phía dưới khi bạn cuộn lên, thì đó cũng là CSS thuần túy.

Tuy nhiên, rất tiếc, đây không phải là một giải pháp ổn định: Trong chrome (có thể do sự cố 1 px được mô tả bởi dotnetCarpenter ở trên), scrollTophoạt động không chính xác bởi 1 pixel, ngay cả khi không có tương tác của người dùng (khi thêm yếu tố). Bạn có thể đặt scrollTop = scrollHeight - clientHeight, nhưng điều đó sẽ giữ div ở vị trí khi một yếu tố khác được thêm vào, còn gọi là tính năng "giữ chính nó ở dưới cùng" không hoạt động nữa.

Vì vậy, trong ngắn hạn, thêm một lượng nhỏ Javascript (thở dài) sẽ khắc phục điều này và đáp ứng tất cả các yêu cầu:

Một cái gì đó như https://codepen.io/anon/pen/pdrLEZ này (ví dụ của Coo), và sau khi thêm một yếu tố vào danh sách, cũng như sau:

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

Trong đó 29 là chiều cao của một dòng.

Vì vậy, khi người dùng cuộn lên nửa dòng (nếu điều đó thậm chí có thể?), Javascript sẽ bỏ qua nó và cuộn xuống phía dưới. Nhưng tôi đoán điều này là không thể bỏ qua. Và, nó sửa lỗi Chrome 1 px.


2

Đây là một giải pháp dựa trên một bài đăng trên blog của Ryan Hunt . Nó phụ thuộc vào thuộc tính overflow-anchorCSS, ghim vị trí cuộn vào một phần tử ở cuối nội dung cuộn.

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>

Lưu ý rằng overflow-anchorhiện tại không hoạt động trong Safari hoặc Edge, vì vậy giải pháp này hiện không hoạt động trong tất cả các trình duyệt.


1

Bạn có thể sử dụng một cái gì đó như thế này,

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

Hãy giải thích nó!
Szabolcs Páll

1.scrollTo là một phương thức cuộn toàn bộ cửa sổ đến các tọa độ cụ thể.2.offsetHeight sẽ cho chiều cao của phần tử của bạn để dòng thứ hai của đoạn mã trên tiếp tục cuộn cửa sổ xuống trong khi bạn đang gán một cái gì đó.
Yashesh Chauhan

0

Đây là cách tôi tiếp cận nó. Chiều cao div của tôi là 650px. Tôi quyết định rằng nếu chiều cao cuộn nằm trong 150px dưới cùng thì tự động cuộn nó. Khác, để lại cho người dùng.

if (container_block.scrollHeight - container_block.scrollTop < 800) {
                    container_block.scrollTo(0, container_block.scrollHeight);
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.