【问题标题】:Scroll to bottom of div?滚动到div的底部?
【发布时间】:2010-09-21 04:48:49
【问题描述】:

我正在使用 Ajax 请求创建一个聊天,我试图让消息 div 滚动到底部,但运气不佳。

我将所有内容都包装在这个 div 中:

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

有没有办法使用JS让它默认滚动到底部?

有没有办法在 ajax 请求后保持滚动到底部?

【问题讨论】:

  • 在很多情况下,这可以通过 CSS-only 来实现。看到这个answer

标签: javascript html ajax chat


【解决方案1】:

仅限 CSS:

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

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

【讨论】:

    【解决方案2】:

    你可以试试下面的代码:

    function scrollToBottom (id) {
       var div = document.getElementById(id);
       div.scrollTop = div.scrollHeight - div.clientHeight;
    }
    

    使用 JQuery 执行 平滑 滚动:

    function scrollSmoothToBottom (id) {
       var div = document.getElementById(id);
       $('#' + id).animate({
          scrollTop: div.scrollHeight - div.clientHeight
       }, 500);
    }
    

    查看JSFiddle上的示例

    这就是为什么会这样:

    参考:scrollTopscrollHeightclientHeight

    【讨论】:

    • 这个答案非常正确,图片真的很有用
    【解决方案3】:

    替代解决方案

    function scrollToBottom(element) {
      element.scroll({ top: element.scrollHeight, behavior: 'smooth' });
    }
    

    【讨论】:

    • 很好的答案,经过测试并且运行良好。谢谢。
    【解决方案4】:

    您可以使用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/bootstrap@4.5.3/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>

    【讨论】:

      【解决方案5】:

      我使用第一个项目 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>

      【讨论】:

        【解决方案6】:

        和你一样,我正在构建一个聊天应用程序,并希望滚动查看最新消息。这最终对我很有效:

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

        【讨论】:

          【解决方案7】:

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

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

          【讨论】:

          • 使用 setTimeout(),它工作正常。使用 Angular 9。节省了我的一天。
          • 乐于助人:)
          【解决方案8】:

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

          var element = document.getElementById("scroll");
          element.scrollIntoView();
          

          【讨论】:

            【解决方案9】:

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

            【讨论】:

              【解决方案10】:

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

              const element = this.shadowRoot.getElementById('my-scrollable-div')
              element.scrollTop = element.scrollHeight
              

              【讨论】:

                【解决方案11】:

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

                window.scrollTo(x=0,y=150);
                

                【讨论】:

                  【解决方案12】:

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

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

                  1) 每个由人员、时间和消息组成的聊天 div 都在一个 for 循环中运行,类为 chatContentbox

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

                  3) 转到最后一个

                  4) scrollIntoView()

                  let lastChatBox = document.querySelectorAll('.chatContentBox'); 
                  lastChatBox = lastChatBox[lastChatBox.length-1]; 
                  lastChatBox.scrollIntoView(); 
                  

                  【讨论】:

                    【解决方案13】:

                    使用:

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

                    【讨论】:

                    • 将 scrollTopMax 更改为 var maxScrollTop = element[0].scrollHeight - element.outerHeight();
                    【解决方案14】:

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

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

                    【讨论】:

                    • 你需要[0]从jquery元素中获取dom元素来获取scrollHeight
                    • 不再重复:$("#mydiv").scrollTop(function() { return this.scrollHeight; });
                    【解决方案15】:

                    平滑使用 Javascript 滚动:

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

                    【讨论】:

                      【解决方案16】:

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

                      myDiv.scrollTop = myDiv.lastChild.offsetTop
                      

                      【讨论】:

                        【解决方案17】:

                        适用于all current browsers 的新方法:

                        this.scrollIntoView(false);
                        

                        【讨论】:

                        • 这应该是公认的答案,因为旧方法不再起作用
                        • 如果 "this" 是 div 中可以滚动到的内容,就会出现这种情况
                        • 方法scrollIntoView在父容器内的子元素上触发。那么如何使用它来:将父级滚动到底部(如原始问题中所述)。
                        • 你可以使用scrollIntoView({ behavior: "smooth", block: "end" });
                        • 在这里查看支持哪些浏览器caniuse.com/?search=scrollIntoView
                        【解决方案18】:
                        var mydiv = $("#scroll");
                        mydiv.scrollTop(mydiv.prop("scrollHeight"));
                        

                        从 jQuery 1.6 开始工作

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

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

                        【讨论】:

                          【解决方案19】:

                          这是我在我的网站上使用的:

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

                          【讨论】:

                          • 这种方法适用于所有浏览器吗?
                          • @PaulDinh:我刚刚调查过这个问题,IE7 和更低版本使用 scrollHeight 存在问题。 IE7 here 似乎确实有解决方法。
                          • 为什么不用scrollTopMax 而不是scrollHeight
                          • 当我动态添加图像时这不起作用:(
                          • “现代”方式是使用 Element.scrollIntoView() -- developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView
                          【解决方案20】:

                          觉得这很有帮助,谢谢。

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

                          对于聊天应用程序,我发现在加载聊天内容后进行此分配很有用,您可能还需要设置短暂的超时时间。

                          【讨论】:

                            【解决方案21】:

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

                            var myDiv = document.getElementById("myDiv");
                            window.scrollTo(0, myDiv.innerHeight);
                            

                            【讨论】:

                              【解决方案22】:

                              Java 脚本:

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

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

                              【讨论】:

                                【解决方案23】:

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

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

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

                                【讨论】:

                                  【解决方案24】:

                                  Javascript 或 jquery:

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

                                  CSS:

                                   .messages
                                   {
                                        height: 100%;
                                        overflow: auto;
                                    }
                                  

                                  【讨论】:

                                    【解决方案25】:

                                    使用jQuery animate:

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

                                    【讨论】:

                                    • 注意这个答案如何使用.stop(),它可以防止多个动画出现问题。
                                    【解决方案26】:

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

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

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

                                    【讨论】:

                                      【解决方案27】:

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

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

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

                                      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/

                                      【讨论】:

                                      • 如何获取动态id?就像&lt;div class="abc"&gt;&lt;div data-bind=attr : {'id': myId } &gt;&lt;/div&gt;&lt;/div&gt; 在这段代码中 myId 是一个变量。如何在脚本中访问此 ID。
                                      • 我不太确定我是否理解您的问题。在我的示例中,“myId”是滚动容器的 id。您想创建多个用户可以滚动的区域吗?
                                      【解决方案28】:

                                      这将让您在文档高度方面一直向下滚动

                                      $('html, body').animate({scrollTop:$(document).height()}, 1000);
                                      

                                      【讨论】:

                                        【解决方案29】:

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

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

                                        如果你想在向下滚动时使用jQuery's animate method添加动画,请检查以下sn-p:

                                        var myDiv = $("#div_id").get(0);
                                        myDiv.animate({
                                            scrollTop: myDiv.scrollHeight
                                          }, 500);
                                        

                                        【讨论】:

                                          【解决方案30】:

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

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

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

                                          【讨论】:

                                          • 我怀疑 $scope.$apply(callback) 会起作用,这会强制对视图进行摘要和重新评估。
                                          • 谢谢!我真的很想知道为什么我不能让它工作并且 $timeout 是问题所在。
                                          • @Wayferer 同样setTimeout(function() { ... }, n)
                                          猜你喜欢
                                          • 2012-07-13
                                          • 1970-01-01
                                          • 2017-03-02
                                          • 1970-01-01
                                          • 1970-01-01
                                          • 1970-01-01
                                          相关资源
                                          最近更新 更多