滚动到 div 的底部?

Scroll to bottom of div?

提问人:kush 提问时间:11/7/2008 最后编辑:Sooraj Abbasikush 更新时间:7/21/2023 访问量:1185406

问:

我正在使用 Ajax 请求创建聊天,并且我试图让消息 div 滚动到底部,但没有太多运气。

我把所有东西都包装在这个div中:

#scroll {
    height:400px;
    overflow:scroll;
}

有没有办法使用 JS 默认将其滚动到底部?

有没有办法在ajax请求后将其滚动到底部?

JavaScript HTML AJAX 聊天

评论

0赞 ashleedawg 8/22/2021
在许多情况下,这可以通过仅使用 CSS 来实现。请看这个答案
0赞 Ravindu Lokumanna 7/17/2023
你可以简单地使用Jquery来实现这一点: $(document).ready(function() { var chatMessagesDiv = $('#scroll'); chatMessagesDiv.scrollTop(chatMessagesDiv[0].scrollHeight);code

答:

1721赞 Paige Ruten 11/7/2008 #1

以下是我在我的网站上使用的内容:

var objDiv = document.getElementById("your_div");
objDiv.scrollTop = objDiv.scrollHeight;

评论

18赞 jondinham 3/2/2012
这种方法适用于所有浏览器吗?
1赞 Sean 8/19/2012
@PaulDinh:我刚刚研究了一下,使用 scrollHeight 的 IE7 及更低版本存在问题。这里似乎确实有 IE7 的解决方法。
2赞 aiven 9/24/2018
为什么不代替?scrollTopMaxscrollHeight
22赞 MichielB 8/14/2020
“现代”方法是使用 Element.scrollIntoView() -- developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView
2赞 Tobia 12/7/2022
@aiven是非标准的,请参阅 caniuse.com/mdn-api_element_scrolltopmaxscrollTopMax
388赞 andsien 4/19/2010 #2

如果您使用 jQuery scrollTop,这会容易得多:

$("#mydiv").scrollTop($("#mydiv")[0].scrollHeight);

评论

29赞 Jimmy Bosse 7/16/2012
你需要 [0] 从 jQuery 元素获取 dom 元素以获取 scrollHeight
55赞 Eric 3/24/2014
不重复自己:$("#mydiv").scrollTop(function() { return this.scrollHeight; });
98赞 DadViegas 9/12/2012 #3

使用 jQuery 动画

$('#DebugContainer').stop().animate({
  scrollTop: $('#DebugContainer')[0].scrollHeight
}, 800);

评论

10赞 kalyfe 8/20/2013
请注意,此答案如何使用 .stop(),这可以防止出现多个动画问题。
39赞 Akira Yamamoto 1/10/2014 #4
var mydiv = $("#scroll");
mydiv.scrollTop(mydiv.prop("scrollHeight"));

从 jQuery 1.6 开始工作

https://api.jquery.com/scrollTop/

http://api.jquery.com/prop/

13赞 Benny Code 6/10/2014 #5

如果您不想依赖 ,以下代码会有所帮助:scrollHeight

$('#scroll').scrollTop(1000000);

评论

7赞 Evgeniy Boytsov 11/20/2020
看起来像一个黑客。1000000 数字是什么意思?
4赞 Bruno Jennrich 7/3/2014 #6

小附录:仅滚动,如果最后一行已经可见。如果滚动一点点,则将内容保留在原处(注意:未使用不同的字体大小进行测试,这可能需要在“>= 比较”中进行一些调整):

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;
4赞 mylescc 8/21/2014 #7

只是一个奖励片段。我正在使用 angular,并且当用户选择与用户的不同对话时,我试图将消息线程滚动到底部。为了确保在使用 ng-repeat for messages 将新数据加载到 div 中后滚动工作,只需将滚动片段包装在超时中即可。

$timeout(function(){
    var messageThread = document.getElementById('message-thread-div-id');
    messageThread.scrollTop = messageThread.scrollHeight;
},0)

这将确保在将数据插入 DOM 后触发 scroll 事件。

评论

0赞 SStanley 8/17/2016
我怀疑 $scope.$apply(callback) 会起作用,这会强制对视图进行摘要和重新评估。
0赞 Wayferer 7/3/2018
谢谢!我真的很想知道为什么我不能让它工作,而$timeout是问题所在。
0赞 KingRider 11/2/2019
@Wayferer相同setTimeout(function() { ... }, n)
71赞 tnt-rox 10/10/2014 #8

适用于所有当前浏览器的较新方法:

this.scrollIntoView(false);

评论

0赞 rbansal 9/13/2020
这应该是公认的答案,因为旧方法不再起作用
2赞 mplungjan 9/24/2020
如果 “this” 是 div 中可以滚动到的内容,则会出现这种情况
0赞 Gil Epshtain 2/9/2021
该方法在父容器内的子元素上触发。那么如何使用它:将父项滚动到底部(如原始问题中所述)。scrollIntoView
6赞 giovannipds 2/20/2021
你可以使用scrollIntoView({ behavior: "smooth", block: "end" });
2赞 Cybernetic 5/13/2022
这将滚动整个页面,而不是目标元素 (chrome)
5赞 Muhammad Soliman 11/20/2014 #9

使用 jQuery,scrollTop 用于为任何给定元素设置 scollbar 的垂直位置。还有一个不错的 jquery scrollTo 插件,用于滚动动画和不同的选项(演示)

var myDiv = $("#div_id").get(0);
myDiv.scrollTop = myDiv.scrollHeight;

如果要在向下滚动时使用 jQuery 的 Animate 方法添加动画,请查看以下代码片段:

var myDiv = $("#div_id").get(0);
myDiv.animate({
    scrollTop: myDiv.scrollHeight
  }, 500);
4赞 Navaneeth 8/13/2015 #10

这将使您可以一直向下滚动文档高度

$('html, body').animate({scrollTop:$(document).height()}, 1000);
6赞 devonj 9/16/2015 #11

发现这真的很有帮助,谢谢。

对于 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 有点混淆。

同样对于聊天应用程序,我发现在加载聊天后进行此分配很有用,您可能还需要短暂停。

5赞 Benkinass 10/9/2015 #12

我遇到了同样的问题,但有一个额外的限制:我无法控制将新元素附加到滚动容器的代码。我在这里找到的例子都不允许我这样做。这是我最终得到的解决方案。

它使用 (https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver),这使得它只能在现代浏览器上使用(尽管存在 polyfills)Mutation Observers

所以基本上代码就是这样做的:

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/

评论

0赞 Irfan Y 10/9/2015
如何获取动态ID?就像在此代码中一样,myId 是一个变量。如何在脚本中访问此 ID。<div class="abc"><div data-bind=attr : {'id': myId } ></div></div>
0赞 Benkinass 10/12/2015
我不太确定我是否理解你的问题。在我的示例中,“myId”是滚动容器的 ID。是否要创建用户可以滚动的多个区域?
183赞 Tho 10/18/2015 #13

请尝试以下代码:

const scrollToBottom = (id) => {
    const element = document.getElementById(id);
    element.scrollTop = element.scrollHeight;
}

您还可以使用 Jquery 使滚动平滑:

const scrollSmoothlyToBottom = (id) => {
    const element = $(`#${id}`);
    element.animate({
        scrollTop: element.prop("scrollHeight")
    }, 500);
}

这是演示

其工作原理如下:

enter image description here

参考:scrollTopscrollHeightclientHeight

4赞 John Dunne 10/29/2015 #14

您还可以使用 jQuery,通过以下方式将动画附加到文档:html,body

$("html,body").animate({scrollTop:$("#div-id")[0].offsetTop}, 1000);

这将导致平滑滚动到 id 为“div-id”的 div 顶部。

7赞 Lay Leangsros 7/19/2016 #15

Javascript 或 jquery:

var scroll = document.getElementById('messages');
   scroll.scrollTop = scroll.scrollHeight;
   scroll.animate({scrollTop: scroll.scrollHeight});

Css:

 .messages
 {
      height: 100%;
      overflow: auto;
  }
0赞 BrianLegg 12/13/2016 #16

我知道这是一个老问题,但这些解决方案都不适合我。我最终使用 offset().top 来获得所需的结果。这是我用来轻轻地将屏幕向下滚动到聊天应用程序中的最后一条消息的方法:

$("#html, body").stop().animate({
     scrollTop: $("#last-message").offset().top
}, 2000);

我希望这对其他人有所帮助。

10赞 Barath Sankar 10/25/2017 #17

Java 脚本:

document.getElementById('messages').scrollIntoView(false);

滚动到当前内容的最后一行。

1赞 aravk33 10/26/2017 #18

一个非常简单的方法是将 设置为 div 的高度。scroll to

var myDiv = document.getElementById("myDiv");
window.scrollTo(0, myDiv.innerHeight);
2赞 mjaque 2/3/2019 #19

滚动到 div 中的最后一个元素:

myDiv.scrollTop = myDiv.lastChild.offsetTop
38赞 adl 4/29/2019 #20

使用 Javascript 平滑滚动:

document.getElementById('messages').scrollIntoView({ behavior: 'smooth', block: 'end' });

-2赞 Mahdi Bagheri Varnosfatherani 7/4/2019 #21

用:

var element= $('element');
var maxScrollTop = element[0].scrollHeight - element.outerHeight();
element.scrollTop(maxScrollTop);

或检查滚动到底部:

    var element = $(element);
    var maxScrollTop = element[0].scrollHeight - element.outerHeight();
    element.on('scroll', function() {
        if ( element.scrollTop() >= maxScrollTop ) {
            alert('scroll to bottom');
        }
    });

评论

0赞 Mahdi Bagheri Varnosfatherani 7/10/2019
将 scrollTopMax 更改为 var maxScrollTop = element[0].scrollHeight - element.outerHeight();
-1赞 veritas 10/3/2019 #22

如果这样做是为了滚动到聊天窗口的底部,请执行以下操作

在聊天中滚动到特定 div 的想法如下

1) 每个由 Person、time 和 message 组成的聊天 div 都运行在带有类 chatContentbox 的 for 循环中

2) querySelectorAll 查找所有此类数组。它可以是 400 个节点(400 个聊天)

3)转到最后一个

4) scrollIntoView()

let lastChatBox = document.querySelectorAll('.chatContentBox'); 
lastChatBox = lastChatBox[lastChatBox.length-1]; 
lastChatBox.scrollIntoView(); 
-2赞 SeekLoad 1/6/2020 #23

有时最简单的就是最好的解决方案: 我不知道这是否会有所帮助,它帮助我滚动它也是我想要的。“y=”越高,它向下滚动得越多,当然“0”意味着顶部,因此例如“1000”可能是底部,或者“2000”或“3000”等,具体取决于您的页面有多长。 这通常适用于带有 onclick 或 onmouseover 的按钮。

window.scrollTo(x=0,y=150);
-2赞 user2341537 2/7/2020 #24

将与可滚动元素顶部的距离设置为元素的总高度。

const element = this.shadowRoot.getElementById('my-scrollable-div')
element.scrollTop = element.scrollHeight
0赞 moreirapontocom 2/17/2020 #25

在我的 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) 函数将停止计时器以允许手动滚动顶部/底部。

8赞 Anatol 3/10/2020 #26

您可以像这样使用 HTML DOM scrollIntoView 方法:

var element = document.getElementById("scroll");
element.scrollIntoView();
12赞 ngShravil.py 5/11/2020 #27

我的场景:我有一个字符串列表,我必须在其中附加用户给出的字符串并自动滚动到列表的末尾。我有固定列表显示的高度,之后它应该溢出。

我尝试@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

评论

1赞 Anjali Sharma 10/13/2020
使用 setTimeout(),它工作正常。使用 angular 9。挽救了我的一天。
5赞 Mike Taverne 7/8/2020 #28

和你一样,我正在构建一个聊天应用程序,并希望将最新消息滚动到视图中。这最终对我来说效果很好:

//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' });
0赞 jocassid 10/7/2020 #29

我使用第一个项目 div 的 Y 坐标与所选项目 div 的 Y 坐标之间的差值。下面是 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>

4赞 Adonis Gaitatzis 11/6/2020 #30

您可以使用 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/[email protected]/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>

39赞 Ahmet Şimşek 12/19/2020 #31

替代解决方案

function scrollToBottom(element) {
  element.scroll({ top: element.scrollHeight, behavior: 'smooth' });
}
3赞 Spankied 7/30/2021 #32

仅限 Css:

.scroll-container {
  overflow-anchor: none;
}

使滚动条在添加子元素时不会锚定在顶部。例如,在聊天底部添加新消息时,将聊天滚动到新消息。

评论

0赞 Viktor Mukhachev 1/20/2023
它应该是“overflow-anchor: auto”吗?
10赞 Marcio Duarte 4/20/2022 #33

如果您的项目面向现代浏览器,您现在可以使用 CSS Scroll Snap 来控制滚动行为,例如将任何动态生成的元素保留在底部。

    .wrapper > div {
        background-color: white;
        border-radius: 5px;
        padding: 5px 10px;
        text-align: center;
        font-family: system-ui, sans-serif;
    }

    .wrapper {
        display: flex;
        padding: 5px;
        background-color: #ccc;
        border-radius: 5px;
        flex-direction: column;
        gap: 5px;
        margin: 10px;
        max-height: 150px;

        /* Control snap from here */
        overflow-y: auto;
        overscroll-behavior-y: contain;
        scroll-snap-type: y mandatory;
    }

    .wrapper > div:last-child {
        scroll-snap-align: start;
    }
<div class="wrapper">
    <div>01</div>
    <div>02</div>
    <div>03</div>
    <div>04</div>
    <div>05</div>
    <div>06</div>
    <div>07</div>
    <div>08</div>
    <div>09</div>
    <div>10</div>
</div>

评论

4赞 Raffi 5/24/2023
请注意,这会将动态生成的元素保留在底部,因此,如果向上滚动,包装器将自动向下滚动到底部。
4赞 PanDe 5/6/2022 #34

为什么不使用简单的CSS来做到这一点呢? 诀窍是在课堂上使用它:

display: flex;
flex-direction: column-reverse;

下面是一个工作示例。

评论

1赞 OXiGEN 12/5/2022
问题在于,可以追加数据的应用逻辑现在必须预置数据。这可能会变得非常混乱,非常快。例如,在聊天程序中,尝试折叠来自单个用户的所有消息,以便仅显示一次用户图标,直到其他用户发送消息。使用附加逻辑非常简单。使用前置逻辑要困难得多。column-reverse
9赞 Klaas Leussink 3/20/2023 #35

无需 JavaScript 的方法 (2023)

这是一个完全不需要任何 JavaScript 的方法,它使用纯 (Flexbox) CSS。我在这里更详细地解释了该方法。

诀窍是将项目放在“content”元素中,该元素包装在充当“滚动器”的 flexbox 元素中。由于项目位于另一个(“内容”)容器中,因此它们不会被“翻转”,而是始终排在底部。事实上,每当添加内容时,滚动条都会滚动到底部。column-reverse

这种方法的优点

除了不依赖 JavaScript 之外,这种方法的一大优点是,当用户开始滚动列表时,滚动位置将固定到用户滚动到的位置。这样可以防止在添加新项目时出现烦人的内容跳转。一旦用户再次滚动回底部,列表将在更新时保持滚动到底部。

Breakdown, click for demo

演示

注意:以下演示中的 JavaScript 仅对演示本身是必需的(将项目添加到列表中,并查看会发生什么)。

let scrollerContent = document.getElementById('scrollerContent');

document.getElementById('addItems').addEventListener('click', function() {
  let newChild = scrollerContent.lastElementChild.cloneNode(true);
  newChild.innerHTML = "Item " + (scrollerContent.children.length + 1);
  scrollerContent.appendChild(newChild);
});
.scroller {
  overflow: auto;
  height: 100px;
  display: flex;
  flex-direction: column-reverse;
}

.scroller .scroller-content .item {
  height: 20px;
  transform: translateZ(0); /* fixes a bug in Safari iOS where the scroller doesn't update */
}
<div class="scroller">
  <div class="scroller-content" id="scrollerContent">
    <div class="item">Item 1</div>
    <div class="item">Item 2</div>
    <div class="item">Item 3</div>
    <div class="item">Item 4</div>
    <div class="item">Item 5</div>
    <div class="item">Item 6</div>
    <div class="item">Item 7</div>
    <div class="item">Item 8</div>
    <div class="item">Item 9</div>
    <div class="item">Item 10</div>
  </div>
</div>
<br/><br/>
<button id="addItems">Add more items</button>

评论

1赞 Abdul Rafay Shaikh 4/4/2023
这是一个很有启发性的,非常酷的把戏。完美工作
0赞 cassepipe 7/1/2023
我使用这个技巧是为了好玩和获利,但我不知道在我真正想要的时候有内容跳跃。这是一个聊天界面,所以某人的新消息不应该滚动到底部,所以这一切都很好,但是我自己发送消息时如何滚动到底部?