![](/img/trans.png)
[英]Typed.js - Keep div scrolled to bottom as div increases in size unless user interacts with scrollbar?
[英]Keep overflow div scrolled to bottom unless user scrolls up
我有一个只有 300 像素大的 div,我希望它在页面加载时滚动到内容的底部。 这个 div 有动态添加的内容,需要一直向下滚动。 现在,如果用户决定向上滚动,我不希望它跳回到底部,直到用户再次向下滚动
是否有可能让一个 div 保持滚动到底部,除非用户向上滚动,并且当用户滚动回到底部时,即使添加了新的动态内容,它也需要将自己保持在底部。 我 go 如何创建它。
我只能使用 CSS 来实现它。
诀窍是使用display: flex;
和flex-direction: column-reverse;
浏览器将底部视为顶部。 假设您的目标浏览器支持flex-box
,唯一需要注意的是标记必须以相反的顺序排列。
这是一个工作示例。 https://codepen.io/jimbol/pen/YVJzBg
这可能会帮助您:
var element = document.getElementById("yourDivID");
element.scrollTop = element.scrollHeight;
[编辑],以匹配评论...
function updateScroll(){
var element = document.getElementById("yourDivID");
element.scrollTop = element.scrollHeight;
}
每当添加内容时,调用函数 updateScroll(),或设置一个计时器:
//once a second
setInterval(updateScroll,1000);
如果您只想在用户没有移动的情况下更新:
var scrolled = false;
function updateScroll(){
if(!scrolled){
var element = document.getElementById("yourDivID");
element.scrollTop = element.scrollHeight;
}
}
$("#yourDivID").on('scroll', function(){
scrolled=true;
});
我刚刚实现了这个,也许你可以使用我的方法。
假设我们有以下 HTML:
<div id="out" style="overflow:auto"></div>
然后我们可以检查它是否滚动到底部:
var out = document.getElementById("out");
// allow 1px inaccuracy by adding 1
var isScrolledToBottom = out.scrollHeight - out.clientHeight <= out.scrollTop + 1;
scrollHeight为您提供元素的高度,包括由于溢出而导致的任何不可见区域。 clientHeight为您提供 CSS 高度,或者以另一种方式说,元素的实际高度。 两种方法都返回没有margin
的高度,所以你不必担心。 scrollTop为您提供垂直滚动的位置。 0 是顶部,最大值是元素的滚动高度减去元素本身的高度。 使用滚动条时,很难(对我来说是在 Chrome 中)将滚动条一直向下移动到底部。 所以我投入了 1px 的误差。 因此即使滚动条距离底部 1px, isScrolledToBottom
也会为真。 您可以将其设置为适合您的任何内容。
然后只需将元素的 scrollTop 设置到底部即可。
if(isScrolledToBottom)
out.scrollTop = out.scrollHeight - out.clientHeight;
我为你做了一个小提琴来展示这个概念:http: //jsfiddle.net/dotnetCarpenter/KpM5j/
编辑:添加代码片段以阐明isScrolledToBottom
何时为true
。
将滚动条粘贴到底部
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>
2020 年可以使用css snap ,但在 Chrome 81 之前布局更改不会触发 re-snap ,纯 css 聊天 ui可以在 Chrome 81 上运行,您也可以检查Can I use CSS snap 。
此演示将捕捉最后一个元素(如果可见),滚动到底部以查看效果。
.container { overflow-y: scroll; overscroll-behavior-y: contain; scroll-snap-type: y proximity; } .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>
编辑
使用scroll-snap-type: y proximity;
, 向上滚动更容易。
$('#yourDiv').scrollTop($('#yourDiv')[0].scrollHeight);
现场演示:http: //jsfiddle.net/KGfG2/
$('#div1').scrollTop($('#div1')[0].scrollHeight);
Or animated:
$("#div1").animate({ scrollTop: $('#div1')[0].scrollHeight}, 1000);
.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>
Run code snippet
查看效果。 (PS:如果Run code snippet
不起作用,试试这个: https ://jsfiddle.net/Yeshen/xm2yLksu/3/)
它是如何工作的:
默认溢出是从上到下滚动。
transform: rotate(180deg)
可以使其从下到上滚动或加载动态块。
基于 Jim Halls 的解决方案和评论。 https://stackoverflow.com/a/44051405/9208887 。
我还添加了一个带有flex 1 1 0%
的元素,以确保文本在容器未满时从顶部开始。
// just to add some numbers, so we can see the effect // the actual solution requires no javascript let num = 1001; const container = document.getElementById("scroll-container"); document.getElementById("adder").onclick = () => container.append( Object.assign(document.createElement("div"), { textContent: num++ }) );
.scroll-wrapper { height: 100px; overflow: auto; display: flex; flex-direction: column-reverse; border: 1px solid black; } .scroll-start-at-top { flex: 1 1 0%; }
<div class="scroll-wrapper"> <span class="scroll-start-at-top"></span> <div id="scroll-container"> <div>1000</div> </div> </div> <button id="adder">Add Text</button>
这是基于Ryan Hunt 的博客文章的解决方案。 它取决于overflow-anchor
CSS 属性,它将滚动位置固定到滚动内容底部的元素。
function addMessage() { const $message = document.createElement('div'); $message.className = 'message'; $message.innerText = `Random number = ${Math.ceil(Math.random() * 1000)}`; $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>
请注意, overflow-anchor
目前在 Safari 中不起作用。
我无法得到前两个答案,其他答案都对我没有帮助。 所以我从 Reddit r/forhire和Upwork向三个人支付了 30 美元,得到了一些非常好的答案。 这个答案应该可以为您节省 90 美元。
HTML
<div id="chatscreen">
<div id="inner">
</div>
</div>
CSS
#chatscreen {
width: 300px;
overflow-y: scroll;
max-height:100px;
}
Javascript
$(function(){
var scrolled = false;
var lastScroll = 0;
var count = 0;
$("#chatscreen").on("scroll", function() {
var nextScroll = $(this).scrollTop();
if (nextScroll <= lastScroll) {
scrolled = true;
}
lastScroll = nextScroll;
console.log(nextScroll, $("#inner").height())
if ((nextScroll + 100) == $("#inner").height()) {
scrolled = false;
}
});
function updateScroll(){
if(!scrolled){
var element = document.getElementById("chatscreen");
var inner = document.getElementById("inner");
element.scrollTop = inner.scrollHeight;
}
}
// Now let's load our messages
function load_messages(){
$( "#inner" ).append( "Test" + count + "<br/>" );
count = count + 1;
updateScroll();
}
setInterval(load_messages,300);
});
HTML
<div id="chatscreen">
</div>
CSS
#chatscreen {
height: 300px;
border: 1px solid purple;
overflow: scroll;
}
Javascript
$(function(){
var isScrolledToBottom = false;
// Now let's load our messages
function load_messages(){
$( "#chatscreen" ).append( "<br>Test" );
updateScr();
}
var out = document.getElementById("chatscreen");
var c = 0;
$("#chatscreen").on('scroll', function(){
console.log(out.scrollHeight);
isScrolledToBottom = out.scrollHeight - out.clientHeight <= out.scrollTop + 10;
});
function updateScr() {
// allow 1px inaccuracy by adding 1
//console.log(out.scrollHeight - out.clientHeight, out.scrollTop + 1);
var newElement = document.createElement("div");
newElement.innerHTML = c++;
out.appendChild(newElement);
console.log(isScrolledToBottom);
// scroll to bottom if isScrolledToBotto
if(isScrolledToBottom) {out.scrollTop = out.scrollHeight - out.clientHeight; }
}
var add = setInterval(updateScr, 1000);
setInterval(load_messages,300); // change to 300 to show the latest message you sent after pressing enter // comment this line and it works, uncomment and it fails
// leaving it on 1000 shows the second to last message
setInterval(updateScroll,30);
});
HTML
<div id="chatscreen"></div>
CSS
#chatscreen {
height: 100px;
overflow: scroll;
border: 1px solid #000;
}
Javascript
$(function(){
// Now let's load our messages
function load_messages(){
$( "#chatscreen" ).append( "<br>Test" );
}
var out = document.getElementById("chatscreen");
var c = 0;
var add = setInterval(function() {
// allow 1px inaccuracy by adding 1
var isScrolledToBottom = out.scrollHeight - out.clientHeight <= out.scrollTop + 1;
load_messages();
// scroll to bottom if isScrolledToBotto
if(isScrolledToBottom) {out.scrollTop = out.scrollHeight - out.clientHeight; }
}, 1000);
setInterval(updateScroll,30);
});
$('#yourDivID').animate({ scrollTop: $(document).height() }, "slow");
return false;
这将使用$(document).height()
属性从#yourDivID
的高度计算 ScrollTop Position,这样即使将动态内容添加到 div,滚动条也将始终位于底部位置。 希望这可以帮助。 但是它也有一个小错误,即使我们向上滚动并将鼠标指针从滚动条上移开,它也会自动到达底部位置。 如果有人可以纠正这一点,那就太好了。
//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;
这是我基于 dotnetCarpenter 的回答的版本。 我的方法是纯 jQuery,我为变量命名以使事情更清晰。发生的情况是,如果内容高度大于容器,我们向下滚动额外的距离以获得所需的结果。
适用于 IE 和 chrome..
吉姆霍尔的答案是可取的,因为当你向上滚动时它确实不会滚动到底部,它也是纯 CSS。
然而,非常不幸的是,这不是一个稳定的解决方案:在 chrome 中(可能是由于上面 dotnetCarpenter 描述的 1-px 问题),即使没有用户交互(在添加元素时), scrollTop
的行为也会不准确 1 个像素。 您可以设置scrollTop = scrollHeight - clientHeight
,但是当添加另一个元素时,这将使 div 保持在适当的位置,即“将自身保持在底部”功能不再起作用。
因此,简而言之,添加少量 Javascript(叹气)将解决此问题并满足所有要求:
像https://codepen.io/anon/pen/pdrLEZ这样的东西(Coo 的例子),在向列表中添加一个元素之后,还有以下内容:
container = ...
if(container.scrollHeight - container.clientHeight - container.scrollTop <= 29) {
container.scrollTop = container.scrollHeight - container.clientHeight;
}
其中 29 是一条线的高度。
因此,当用户向上滚动半行时(如果可能的话?),Javascript 将忽略它并滚动到底部。 但我想这是可以忽略的。 而且,它修复了 Chrome 1 px 的东西。
你可以使用这样的东西,
var element = document.getElementById("yourDivID");
window.scrollTo(0,element.offsetHeight);
以下是您需要的(我尽了最大努力,一路上进行了大量的谷歌搜索):
<html>
<head>
<script>
// no jquery, or other craziness. just
// straight up vanilla javascript functions
// to scroll a div's content to the bottom
// if the user has not scrolled up. Includes
// a clickable "alert" for when "content" is
// changed.
// this should work for any kind of content
// be it images, or links, or plain text
// simply "append" the new element to the
// div, and this will handle the rest as
// proscribed.
let scrolled = false; // at bottom?
let scrolling = false; // scrolling in next msg?
let listener = false; // does element have content changed listener?
let contentChanged = false; // kind of obvious
let alerted = false; // less obvious
function innerHTMLChanged() {
// this is here in case we want to
// customize what goes on in here.
// for now, just:
contentChanged = true;
}
function scrollToBottom(id) {
if (!id) { id = "scrollable_element"; }
let DEBUG = 0; // change to 1 and open console
let dstr = "";
let e = document.getElementById(id);
if (e) {
if (!listener) {
dstr += "content changed listener not active\n";
e.addEventListener("DOMSubtreeModified", innerHTMLChanged);
listener = true;
} else {
dstr += "content changed listener active\n";
}
let height = (e.scrollHeight - e.offsetHeight); // this isn't perfect
let offset = (e.offsetHeight - e.clientHeight); // and does this fix it? seems to...
let scrollMax = height + offset;
dstr += "offsetHeight: " + e.offsetHeight + "\n";
dstr += "clientHeight: " + e.clientHeight + "\n";
dstr += "scrollHeight: " + e.scrollHeight + "\n";
dstr += "scrollTop: " + e.scrollTop + "\n";
dstr += "scrollMax: " + scrollMax + "\n";
dstr += "offset: " + offset + "\n";
dstr += "height: " + height + "\n";
dstr += "contentChanged: " + contentChanged + "\n";
if (!scrolled && !scrolling) {
dstr += "user has not scrolled\n";
if (e.scrollTop != scrollMax) {
dstr += "scroll not at bottom\n";
e.scroll({
top: scrollMax,
left: 0,
behavior: "auto"
})
e.scrollTop = scrollMax;
scrolling = true;
} else {
if (alerted) {
dstr += "alert exists\n";
} else {
dstr += "alert does not exist\n";
}
if (contentChanged) { contentChanged = false; }
}
} else {
dstr += "user scrolled away from bottom\n";
if (!scrolling) {
dstr += "not auto-scrolling\n";
if (e.scrollTop >= scrollMax) {
dstr += "scroll at bottom\n";
scrolled = false;
if (alerted) {
dstr += "alert exists\n";
let n = document.getElementById("alert");
n.remove();
alerted = false;
contentChanged = false;
scrolled = false;
}
} else {
dstr += "scroll not at bottom\n";
if (contentChanged) {
dstr += "content changed\n";
if (!alerted) {
dstr += "alert not displaying\n";
let n = document.createElement("div");
e.append(n);
n.id = "alert";
n.style.position = "absolute";
n.classList.add("normal-panel");
n.classList.add("clickable");
n.classList.add("blink");
n.innerHTML = "new content!";
let nposy = parseFloat(getComputedStyle(e).height) + 18;
let nposx = 18 + (parseFloat(getComputedStyle(e).width) / 2) - (parseFloat(getComputedStyle(n).width) / 2);
dstr += "nposx: " + nposx + "\n";
dstr += "nposy: " + nposy + "\n";
n.style.left = nposx;
n.style.top = nposy;
n.addEventListener("click", () => {
dstr += "clearing alert\n";
scrolled = false;
alerted = false;
contentChanged = false;
n.remove();
});
alerted = true;
} else {
dstr += "alert already displayed\n";
}
} else {
alerted = false;
}
}
} else {
dstr += "auto-scrolling\n";
if (e.scrollTop >= scrollMax) {
dstr += "done scrolling";
scrolling = false;
scrolled = false;
} else {
dstr += "still scrolling...\n";
}
}
}
}
if (DEBUG && dstr) console.log("stb:\n" + dstr);
setTimeout(() => { scrollToBottom(id); }, 50);
}
function scrollMessages(id) {
if (!id) { id = "scrollable_element"; }
let DEBUG = 1;
let dstr = "";
if (scrolled) {
dstr += "already scrolled";
} else {
dstr += "got scrolled";
scrolled = true;
}
dstr += "\n";
if (contentChanged && alerted) {
dstr += "content changed, and alerted\n";
let n = document.getElementById("alert");
if (n) {
dstr += "alert div exists\n";
let e = document.getElementById(id);
let nposy = parseFloat(getComputedStyle(e).height) + 18;
dstr += "nposy: " + nposy + "\n";
n.style.top = nposy;
} else {
dstr += "alert div does not exist!\n";
}
} else {
dstr += "content NOT changed, and not alerted";
}
if (DEBUG && dstr) console.log("sm: " + dstr);
}
setTimeout(() => { scrollToBottom("messages"); }, 1000);
/////////////////////
// HELPER FUNCTION
// simulates adding dynamic content to "chat" div
let count = 0;
function addContent() {
let e = document.getElementById("messages");
if (e) {
let br = document.createElement("br");
e.append("test " + count);
e.append(br);
count++;
}
}
</script>
<style>
button {
border-radius: 5px;
}
#container {
padding: 5px;
}
#messages {
background-color: blue;
border: 1px inset black;
border-radius: 3px;
color: white;
padding: 5px;
overflow-x: none;
overflow-y: auto;
max-height: 100px;
width: 100px;
margin-bottom: 5px;
text-align: left;
}
.bordered {
border: 1px solid black;
border-radius: 5px;
}
.inline-block {
display: inline-block;
}
.centered {
text-align: center;
}
.normal-panel {
background-color: #888888;
border: 1px solid black;
border-radius: 5px;
padding: 2px;
}
.clickable {
cursor: pointer;
}
</style>
</head>
<body>
<div id="container" class="bordered inline-block centered">
<div class="inline-block">My Chat</div>
<div id="messages" onscroll="scrollMessages('messages')">
test<br>
test<br>
test<br>
test<br>
test<br>
test<br>
test<br>
test<br>
test<br>
test<br>
</div>
<button onclick="addContent();">Add Content</button>
</div>
</body>
</html>
注意:您可能需要调整scrollToBottom
和scrollMessages
中的警报位置( nposx
和nposy
)以满足您的需要......
还有一个链接到我自己的工作示例,托管在我的服务器上: https ://night-stand.ca/jaretts_tests/chat_scroll.html
这是我的处理方式。 我的 div 高度是 650 像素。 我决定如果滚动高度在底部的 150px 范围内,则自动滚动它。 否则,留给用户。
if (container_block.scrollHeight - container_block.scrollTop < 800) {
container_block.scrollTo(0, container_block.scrollHeight);
}
我设法让这个工作。 诀窍是计算:(a)当前 div 用户滚动位置和(b)div 滚动高度,两者都在添加新元素之前。
如果 a === b,我们知道用户在添加新元素之前位于底部。
let div = document.querySelector('div.scrollableBox');
let span = document.createElement('span');
span.textContent = 'Hello';
let divCurrentUserScrollPosition = div.scrollTop + div.offsetHeight;
let divScrollHeight = div.scrollHeight;
// We have the current scroll positions saved in
// variables, so now we can append the new element.
div.append(span);
if ((divScrollHeight === divCurrentUserScrollPosition)) {
// Scroll to bottom of div
div.scrollTo({ left: 0, top: div.scrollHeight });
}
我试图对 Bootstrap 5 做同样的事情。我正在编写的页面是一个单窗口 html 工具,我希望两列具有可滚动的内容,并且一个需要反转,因为它是一个日志(另一个不太可能滚动,除非故意这样做)。 列表和它们的标题也是底部锚定的,我很难让标题保持在弹性可滚动列表的顶部。
多亏了上面的例子,我可以弄清楚我缺少什么并获得正确的类类型来使其工作。
这是我的完整示例。 在我的实际应用程序中,另外两列左侧的第三列具有mh-100 col overflow-auto
类,并且不需要内部行/列,因为没有标题可以粘贴在顶部(如果视口是,它只会正常滚动太小)。 列表有一个 ID,我用来选择和添加它们或删除顶部元素(这是反向列表中底部的<li>
项)。
这里提供了一个较小的版本:
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous"> <div class="vh-100 w-75 container-fluid"> <h1>2nd Level Scrolling Example</h1> <div class="h-75 row align-items-end"> <div class="mh-100 col d-flex flex-column"> <div class="row align-items-end"> <div class="col"><h3>Normal scroll list, grow on top</h3></div> </div> <div class="row align-items-end overflow-auto"> <div class="mh-100 col"> <ul class="list-group"> <li>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin ut</li> <li>tortor eu ex tincidunt pretium non eu nisl. Ut eu libero ac velit</li> <li>ultricies dapibus. Donec id augue scelerisque, gravida est ut,</li> <li>commodo sapien. Interdum et malesuada fames ac ante ipsum primis</li> <li>in faucibus. Suspendisse volutpat fermentum finibus. Cras egestas</li> <li>tempor tempor. Suspendisse potenti. Mauris ac tellus ultrices lectus</li> <li>accumsan pellentesque. Nullam semper, nisi nec euismod ultrices, leo</li> <li>sem bibendum sapien, in rutrum sapien massa id mi.</li> </ul> </div> </div> </div> <div class="mh-100 col d-flex flex-column"> <div class="row align-items-end"> <div class="col"><h3>Reverse scroll list, grow on bottom</h3></div> </div> <div class="row align-items-end d-flex flex-column-reverse overflow-auto"> <div class="mh-100 col"> <ul class="list-group"> <li>sem bibendum sapien, in rutrum sapien massa id mi.</li> <li>accumsan pellentesque. Nullam semper, nisi nec euismod ultrices, leo</li> <li>tempor tempor. Suspendisse potenti. Mauris ac tellus ultrices lectus</li> <li>in faucibus. Suspendisse volutpat fermentum finibus. Cras egestas</li> <li>commodo sapien. Interdum et malesuada fames ac ante ipsum primis</li> <li>ultricies dapibus. Donec id augue scelerisque, gravida est ut,</li> <li>tortor eu ex tincidunt pretium non eu nisl. Ut eu libero ac velit</li> <li>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin ut</li> </ul> </div> </div> </div> </div> </div>
如果您的视口高度小于整体内容,则标题应位于列表顶部,页面底部的所有内容(实际上是视口高度的 75%,但在本例中,标题不占用空间它是为)而设计的。
注意:我并不是真正的网络开发人员,只是为日常工作编写一些方便的基于 html 的工具,因此非常欢迎发表评论。
我发现最用户友好的解决方案是将scroll-snap-align
方法与一点点 Javascript 结合起来。 前一种解决方案本身的问题是快照太强,您必须滚动很远才能摆脱它。
取而代之的是,我们可以在容器滚动到底部时使用捕捉动态,然后在用户向上滚动超过某个阈值时禁用它。
该解决方案还有一个额外的好处,即它是一种渐进式增强:如果用户禁用了 Javascript,它将回退到仅使用 CSS 的方法。
const container = document.getElementById("container"); const snap = document.getElementById("snap"); // Scroll the view to the bottom once initially container.scrollTop = container.scrollHeight; container.addEventListener("scroll", (event) => { const target = event.currentTarget; const scroll = target.scrollTop; const maxScroll = target.scrollHeight - target.clientHeight; const threshold = 50; // px isScrollBottomedOut = maxScroll - scroll < threshold; // If the user scrolls up more than the threshold, disable snapping // If the user scrolls down again, reenable snapping snap.style.display = isScrollBottomedOut ? "block" : "none"; });
#container { width: 200px; height: 500px; overflow-y: auto; overflow-x: hidden; -webkit-overflow-scrolling: touch; -ms-scroll-chaining: none; overscroll-behavior: contain; -ms-scroll-snap-type: y proximity; scroll-snap-type: y proximity; border: 2px solid black; } #snap { scroll-snap-align: end; }
<div id="container"> <ol> <li>item</li> <li>item</li> <li>item</li> <li>item</li> <li>item</li> <li>item</li> <li>item</li> <li>item</li> <li>item</li> <li>item</li> <li>item</li> <li>item</li> <li>item</li> <li>item</li> <li>item</li> <li>item</li> <li>item</li> <li>item</li> <li>item</li> <li>item</li> <li>item</li> <li>item</li> <li>item</li> <li>item</li> <li>item</li> <li>item</li> <li>item</li> <li>item</li> <li>item</li> <li>item</li> <li>item</li> <li>item</li> <li>item</li> <li>item</li> <li>item</li> <li>item</li> <li>item</li> <li>item</li> <li>item</li> <li>item</li> </ol> <!-- This is the snapping target, if visible --> <div id="snap"></div> </div>
有一个名为*.scrollIntoView
的方法。 运行此方法一次后,它使容器在底部滚动。 即使在向容器中添加新内容后,它也会滚动到底部。
import {
AfterViewInit,
Directive,
ElementRef,
} from '@angular/core';
@Directive({
selector: '[aeScrollIntoView]',
})
export class ScrollIntoViewDirective implements AfterViewInit {
constructor(private readonly el: ElementRef<HTMLDivElement>) {}
ngAfterViewInit(): void {
this.el.nativeElement.scrollIntoView({ behavior: 'smooth' });
}
}
<div aeScrollIntoView>
Your long and dynamic content.
Whenever new content is added to this container, it scrolls to the bottom.
<div>
使用 Bootstrap 5:
<div class="overflow-auto d-flex flex-column-reverse" style="max-width: 300px; max-height: 300px;"> <div> <!-- Your content here --> </div> </div>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.