简体   繁体   English

滚动到 div 的底部?

[英]Scroll to bottom of div?

I am creating a chat using Ajax requests and I'm trying to get messages div to scroll to the bottom without much luck.我正在使用 Ajax 请求创建聊天,我试图让消息 div 滚动到底部,但运气不佳。

I am wrapping everything in this div:我将所有内容包装在这个 div 中:

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

Is there a way to keep it scrolled to the bottom by default using JS?有没有办法使用JS让它默认滚动到底部?

Is there a way to keep it scrolled to the bottom after an ajax request?在 ajax 请求后,有没有办法让它滚动到底部?

Here's what I use on my site:这是我在我的网站上使用的内容:

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

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

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

You can try the code below:你可以试试下面的代码:

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

To perform a smooth scroll with JQuery:要使用 JQuery 执行平滑滚动:

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

See the example on JSFiddle查看该示例的jsfiddle

Here's why this works:这就是为什么这样做的原因:

在此处输入图片说明

Ref: scrollTop , scrollHeight , clientHeight参考: scrollTopscrollHeightclientHeight

using jQuery animate :使用jQuery 动画

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

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

this.scrollIntoView(false);
var mydiv = $("#scroll");
mydiv.scrollTop(mydiv.prop("scrollHeight"));

Works from jQuery 1.6从 jQuery 1.6 开始工作

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

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

使用 Javascript平滑滚动:

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

If your project targets modern browsers , you can now use CSS Scroll Snap to control the scrolling behavior, such as keeping any dynamically generated element at the bottom.如果您的项目面向现代浏览器,您现在可以使用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>

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

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

Java Script: Java脚本:

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

Scrolls to the last line of the content present.滚动到当前内容的最后一行。

My Scenario: I had an list of string, in which I had to append a string given by a user and scroll to the end of the list automatically.我的场景:我有一个字符串列表,我必须在其中附加用户给出的字符串并自动滚动到列表的末尾。 I had fixed height of the display of the list, after which it should overflow.我有固定的列表显示高度,之后它应该溢出。

I tried @Jeremy Ruten's answer, it worked, but it was scrolling to the (n-1)th element.我尝试了@Jeremy Ruten 的回答,它奏效了,但它正在滚动到第 (n-1) 个元素。 If anybody is facing this type of issue, you can use setTimeOut() method workaround.如果有人面临此类问题,您可以使用setTimeOut()方法解决方法。 You need to modify the code to below:您需要将代码修改为以下:

setTimeout(() => {
    var objDiv = document.getElementById('div_id');
    objDiv.scrollTop = objDiv.scrollHeight
}, 0)

Here is the StcakBlitz link I have created which shows the problem and its solution : https://stackblitz.com/edit/angular-ivy-x9esw8这是我创建的 StcakBlitz 链接,其中显示了问题及其解决方案: https ://stackblitz.com/edit/angular-ivy-x9esw8

Javascript or jquery: Javascript 或 jquery:

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

Css: css:

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

You can use the HTML DOM scrollIntoView Method like this:您可以像这样使用 HTML DOM scrollIntoView 方法:

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

Using jQuery, scrollTop is used to set the vertical position of scollbar for any given element.使用 jQuery, scrollTop用于为任何给定元素设置 scollbar 的垂直位置。 there is also a nice jquery scrollTo plugin used to scroll with animation and different options ( demos )还有一个很好的jquery scrollTo 插件,用于滚动动画和不同的选项(演示

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

if you want to use jQuery's animate method to add animation while scrolling down, check the following snippet:如果您想使用jQuery 的 animate 方法在向下滚动时添加动画,请检查以下代码段:

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

Found this really helpful, thank you.发现这真的很有帮助,谢谢。

For the Angular 1.X folks out there:对于 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;

  }
]);

Just because the wrapping in jQuery elements versus HTML DOM elements gets a little confusing with angular.只是因为 jQuery 元素与 HTML DOM 元素的包装与 angular 有点混淆。

Also for a chat application, I found making this assignment after your chats were loaded to be useful, you also might need to slap on short timeout as well.同样对于聊天应用程序,我发现在加载聊天后进行此分配很有用,您可能还需要短暂超时。

I have encountered the same problem, but with an additional constraint: I had no control over the code that appended new elements to the scroll container.我遇到了同样的问题,但有一个额外的限制:我无法控制将新元素附加到滚动容器的代码。 None of the examples I found here allowed me to do just that.我在这里找到的所有示例都不允许我这样做。 Here is the solution I ended up with .这是我最终得到的解决方案。

It uses Mutation Observers ( https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver ) which makes it usable only on modern browsers (though polyfills exist)它使用Mutation Observers ( https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver ),这使得它只能在现代浏览器上使用(尽管存在 polyfills)

So basically the code does just that :所以基本上代码就是这样做的:

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

I made a fiddle to demonstrate the concept : https://jsfiddle.net/j17r4bnk/我做了一个小提琴来演示这个概念: https : //jsfiddle.net/j17r4bnk/

small addendum: scrolls only, if last line is already visible.小附录:仅滚动,如果最后一行已经可见。 if scrolled a tiny bit, leaves the content where it is (attention: not tested with different font sizes. this may need some adjustments inside ">= comparison"):如果滚动一点,将内容留在原处(注意:未使用不同的字体大小进行测试。这可能需要在“>=比较”中进行一些调整):

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;

Just as a bonus snippet.就像一个奖励片段。 I'm using angular and was trying to scroll a message thread to the bottom when a user selected different conversations with users.我正在使用 angular 并试图在用户选择与用户的不同对话时将消息线程滚动到底部。 In order to make sure that the scroll works after the new data had been loaded into the div with the ng-repeat for messages, just wrap the scroll snippet in a timeout.为了确保在使用 ng-repeat 消息将新数据加载到 div 后滚动工作,只需将滚动片段包装在超时中。

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

That will make sure that the scroll event is fired after the data has been inserted into the DOM.这将确保在数据插入 DOM 后触发滚动事件。

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

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

You can also, using jQuery, attach an animation to html,body of the document via:您还可以使用 jQuery,通过以下方式将动画附加到文档的html,body中:

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

which will result in a smooth scroll to the top of the div with id "div-id".这将导致平滑滚动到 id 为“div-id”的 div 的顶部。

alternative solution替代方案

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

Like you, I'm building a chat app and want the most recent message to scroll into view.像您一样,我正在构建一个聊天应用程序,并希望将最新消息滚动到视图中。 This ultimately worked well for me:这最终对我来说效果很好:

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

Why not use simple CSS to do this?为什么不使用简单的 CSS 来做到这一点?

The trick is to use display: flex;诀窍是使用 display: flex; and flex-direction: column-reverse;和 flex-direction: column-reverse;

Here is a working example. https://codepen.io/jimbol/pen/YVJzBg

A very simple method to this is to set the scroll to to the height of the div.一个非常简单的方法是将scroll to设置为 div 的高度。

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

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

myDiv.scrollTop = myDiv.lastChild.offsetTop

On my Angular 6 application I just did this:在我的 Angular 6 应用程序中,我只是这样做了:

postMessage() {
  // post functions here
  let history = document.getElementById('history')
  let interval    
  interval = setInterval(function() {
    history.scrollTop = history.scrollHeight
    clearInterval(interval)
  }, 1)
}

The clearInterval(interval) function will stop the timer to allow manual scroll top / bottom. clearInterval(interval) 函数将停止计时器以允许手动滚动顶部/底部。

I know this is an old question, but none of these solutions worked out for me.我知道这是一个老问题,但这些解决方案都不适合我。 I ended up using offset().top to get the desired results.我最终使用 offset().top 来获得所需的结果。 Here's what I used to gently scroll the screen down to the last message in my chat application:这是我用来轻轻向下滚动屏幕到聊天应用程序中的最后一条消息的内容:

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

I hope this helps someone else.我希望这对其他人有帮助。

I use the difference between the Y coordinate of the first item div and the Y coordinate of the selected item div.我使用了第一个项目div的Y坐标和所选项目div的Y坐标之间的差值。 Here is the JavaScript/JQuery code and the html:这是 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>

You can use the Element.scrollTo() method.您可以使用Element.scrollTo()方法。

It can be animated using the built-in browser/OS animation, so it's super smooth.它可以使用内置的浏览器/操作系统动画进行动画处理,因此非常流畅。

 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>

Css only:仅 CSS:

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

Makes it so the scroll bar doesn't stay anchored to the top when a child element is added.使滚动条在添加子元素时不会停留在顶部。 For example, when new message is added at the bottom of chat, scroll chat to new message.例如,在聊天底部添加新消息时,将聊天滚动到新消息。

use : 采用 :

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

or check scroll to bottom : 或检查滚动到底部:

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

If this is being done for scrolling to the bottom of chat window, do the following如果这样做是为了滚动到聊天窗口的底部,请执行以下操作

The idea of scrolling to a particular div in the chat was the following在聊天中滚动到特定 div 的想法如下

1) Each chat div consisting of Person, time and message is run in a for loop with class chatContentbox 1) 每个由人员、时间和消息组成的聊天 div 都在一个带有 chatContentbox 类的 for 循环中运行

2) querySelectorAll finds all such arrays. 2) querySelectorAll 找到所有这样的数组。 It could be 400 nodes (400 chats)它可能是 400 个节点(400 个聊天)

3) go to the last one 3) 转到最后一个

4) scrollIntoView() 4)scrollIntoView()

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

Sometimes the most simple is the best solution: I do not know if this will help, it helped me to scroll it were ever I wanted too.有时,最简单的就是最好的解决方案:我不知道这是否会有所帮助,它也帮助我在我想要的时候滚动它。 The higher the "y=" is,the more down it scrolls and of course "0" means top, so there for example "1000" could be bottom, or "2000" or "3000" and so on, depending how long your page is. “y=”越高,滚动越向下,当然“0”表示顶部,所以例如“1000”可能是底部,或者“2000”或“3000”等等,这取决于你的页面是。 This usually works in a button with onclick or onmouseover.这通常适用于带有 onclick 或 onmouseover 的按钮。

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

I am creating a chat using Ajax requests and I'm trying to get messages div to scroll to the bottom without much luck.我正在使用Ajax请求创建聊天,并且试图使消息div滚动到底部而没有太多运气。

I am wrapping everything in this div:我将所有内容包装在这个div中:

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

Is there a way to keep it scrolled to the bottom by default using JS?有没有一种方法可以使用JS将其默认滚动到底部?

Is there a way to keep it scrolled to the bottom after an ajax request?有没有办法在ajax请求后将其滚动到底部?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM