除非用户向上滚动,否则保持溢出 div 滚动到底部
Posted
技术标签:
【中文标题】除非用户向上滚动,否则保持溢出 div 滚动到底部【英文标题】:Keep overflow div scrolled to bottom unless user scrolls up 【发布时间】:2013-09-07 23:42:23 【问题描述】:我有一个只有 300 像素大的 div,我希望它在页面加载时滚动到内容的底部。这个 div 有动态添加的内容,需要一直向下滚动。现在,如果用户决定向上滚动,我不希望它跳回底部,直到用户再次向下滚动
是否有可能让一个 div 保持滚动到底部,除非用户向上滚动并且当用户滚动回到底部时,即使添加了新的动态内容,它也需要将自己保持在底部。我将如何创建这个。
【问题讨论】:
使用css位置顶部保持在底部position : relative; bottom:0;
。用户滚动后删除 css 属性。
既然你没有接受答案,我想问一下:它对你有用吗?
听起来像是你想要完成的聊天框
对于这个问题的新手,应该在 2020 尝试css snap。
Here's css-only 方法适用于许多情况。
【参考方案1】:
我只能使用 CSS 来实现这一点。
诀窍是使用display: flex;
和flex-direction: column-reverse;
浏览器将底部视为顶部。假设您的目标浏览器支持flex-box
,唯一需要注意的是标记必须以相反的顺序排列。
这是一个工作示例。 https://codepen.io/jimbol/pen/YVJzBg
【讨论】:
您可以通过添加一个额外的包装器并将overflow:auto; display:flex; flex-direction:column-reverse;
应用到外部包装器而不是内部包装器来避免需要反转内容。
可能是最好的解决方案,因为它不需要 javascript。
@NathanArthur 实际上,如果你只是在容器下添加一个 div 来取消所有内容:codepen.io/anon/pen/pdrLEZ
不幸的是,这个解决方案似乎不适用于 Firefox :(
现在是 2020 年 10 月。我已经检查过它也在 Firefox 上运行。感谢您的快速解决方案。【参考方案2】:
这可能会对您有所帮助:
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;
);
【讨论】:
这很好地在页面加载时将其滚动到底部,但是当添加动态内容时我需要它保持在底部,除非用户向上滚动。 据我所知,当用户滚动回底部时,这不会重新启用动态滚动... @TvE 我们不能添加支持吗? 错误的解决方案。对于这个轻微的问题,没有理由添加setInterval
。
@ethancrist 然而,你别无选择......耸耸肩。【参考方案3】:
我刚刚实现了这个,也许你可以使用我的方法。
假设我们有以下 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 的误差。所以isScrolledToBottom
将是真的,即使滚动条距离底部 1px。您可以将其设置为适合您的任何内容。
那么只需将元素的scrollTop设置到底部即可。
if(isScrolledToBottom)
out.scrollTop = out.scrollHeight - out.clientHeight;
我为你做了一个小提琴来展示这个概念:http://jsfiddle.net/dotnetCarpenter/KpM5j/
编辑:
添加了代码 sn-p 以阐明 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>
【讨论】:
这实际上是完成所述问题的唯一解决方案。并且应该被标记为正确答案。 @dotnetCarpenter:在我看来你需要if(!isScrolledToBottom)
:测试对我来说似乎是错误的(并且在我修复它之前无法在 my 代码中工作) .
@luskwater 你能提供一个fsfiddle来解决你的问题吗?我不明白out.scrollHeight - out.clientHeight <= out.scrollTop + 1
的问题。您是否在 CSS 中使用填充?
这就是我要找的。而且,这就是 OP 提出的问题的答案。谢谢 dotnetCarperter。
也许我很困惑,但它不应该是“if (!isScrolledToBottom)”吗?添加 not 似乎可以满足 OP 的要求。【参考方案4】:
在 2020 年,您可以使用 css snap,但在 Chrome 81 之前布局更改将 not trigger re-snap,pure css chat 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;
,更容易向上滚动。
【讨论】:
这值得一枚奖牌。正是我想要的:) 它在 Firefox 79 中有效,但仅当您使用滚动条滚动时,如果您使用鼠标滚轮它不会触发回弹。 @aatifshaikh 我更新了答案,现在你可以更轻松地向上滚动了。 接近范围取决于可滚动高度。如果您的聊天视图高于 2 或 3 个聊天气泡,当您向上滚动多达 2 或 3 条消息时,它会再次快速回到末尾(除非您滚动数百像素),这使得该方法无法使用。共享sn-p之所以有效,是因为view的高度太小了。【参考方案5】:$('#yourDiv').scrollTop($('#yourDiv')[0].scrollHeight);
现场演示:http://jsfiddle.net/KGfG2/
【讨论】:
这很好地在页面加载时将其滚动到底部,但是当添加动态内容时我需要它保持在底部,除非用户向上滚动。 这非常有效。我正在使用动态内容进行更新,并且滚动条始终位于底部。 这仅适用于具有固定高度的 div。不适用于可变 div 高度【参考方案6】:$('#div1').scrollTop($('#div1')[0].scrollHeight);
Or animated:
$("#div1").animate( scrollTop: $('#div1')[0].scrollHeight, 1000);
【讨论】:
这很好地在页面加载时将其滚动到底部,但是当添加动态内容时我需要它保持在底部,除非用户向上滚动。 这在第一次拍摄时 div 增长很多时不起作用。例如在 Angular-js、react js、Meteor Blaze 模板加载中,这将不起作用。 这对我有用。我认为如果有问题的 div 将保持一致的高度,它会很好。尚未使用动态高度对其进行测试。【参考方案7】:.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)
可以让它从下到上滚动或加载动态块。
-
最初的想法:
https://blog.csdn.net/yeshennet/article/details/88880252
【讨论】:
请添加更多关于您的代码如何解决 OP 问题的说明 1,增加了一个额外的介绍。 2、请Run code snippet
,直接看效果。
我没有出现运行代码 sn-p 按钮。检查您的格式
太好了。请在您的答案中包含链接
非常有创意的解决方案。但是,它会反转鼠标滚轮的正常操作。要向上,我必须“向下”滚动,反之亦然。【参考方案8】:
$('#yourDivID').animate( scrollTop: $(document).height() , "slow");
return false;
这将使用$(document).height()
属性从#yourDivID
的高度计算ScrollTop Position,这样即使将动态内容添加到div,滚动条也将始终位于底部位置。希望这可以帮助。但是它也有一个小错误,即使我们向上滚动并将鼠标指针从滚动条上移开,它也会自动到达底部位置。如果有人能纠正那也很好。
【讨论】:
【参考方案9】:这是基于a blog post by 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 中不起作用。
【讨论】:
【参考方案10】://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..
【讨论】:
【参考方案11】:Jim Hall 的回答更可取,因为当你向上滚动时它确实不会滚动到底部,它也是纯 CSS。
非常不幸的是,这不是一个稳定的解决方案:在 chrome 中(可能是由于上面 dotnetCarpenter 描述的 1-px 问题),scrollTop
的行为不准确 1 像素,即使没有用户交互(在添加元素时)。您可以设置scrollTop = scrollHeight - clientHeight
,但是当添加另一个元素时,这将使 div 保持在原位,即“将自身保持在底部”功能不再起作用。
因此,简而言之,添加少量 Javascript(叹气)将解决此问题并满足所有要求:
类似于https://codepen.io/anon/pen/pdrLEZ this(Coo 的示例),在将元素添加到列表后,还有以下内容:
container = ...
if(container.scrollHeight - container.clientHeight - container.scrollTop <= 29)
container.scrollTop = container.scrollHeight - container.clientHeight;
其中 29 是一行的高度。
所以,当用户向上滚动半行时(如果可能的话?),Javascript 将忽略它并滚动到底部。但我想这是可以忽略的。而且,它修复了 Chrome 1 px 的问题。
【讨论】:
【参考方案12】:你可以使用这样的东西,
var element = document.getElementById("yourDivID");
window.scrollTo(0,element.offsetHeight);
【讨论】:
请解释一下! 1.scrollTo 是一种将整个窗口滚动到特定坐标的方法。2.offsetHeight 将给出元素的高度,因此上述代码的第二行在您分配时会继续向下滚动窗口东西。【参考方案13】:我无法得到前两个答案,其他答案都对我没有帮助。所以我从 Reddit r/forhire 和 Upwork 向三个人支付了 30 美元,得到了一些非常好的答案。这个答案应该可以为您节省 90 美元。
Justin Hundley / The Site Bros 的解决方案
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);
);
Preview the site bros' solution
portfolio
Lermex / Sviatoslav Chumakov 的解决方案
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);
);
Preview Sviatoslav's solution
portfolio
Igor Rusinov 的解决方案
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);
);
Preview Igor's solution
portfolio
【讨论】:
【参考方案14】:以下内容可以满足您的需求(我已尽了最大努力,一路上进行了大量的谷歌搜索):
<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
中的alert 位置(nposx
和nposy
)以满足您的需求...
还有一个指向我自己的工作示例的链接,托管在我的服务器上:https://night-stand.ca/jaretts_tests/chat_scroll.html
【讨论】:
【参考方案15】:这就是我的处理方式。我的 div 高度是 650 像素。我决定如果滚动高度在底部的 150px 范围内,则自动滚动它。否则,留给用户。
if (container_block.scrollHeight - container_block.scrollTop < 800)
container_block.scrollTo(0, container_block.scrollHeight);
【讨论】:
【参考方案16】:我设法让这个工作。诀窍是在添加新元素之前计算:(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 );
【讨论】:
【参考方案17】:我试图用 Bootstrap 5 来做同样的事情。我正在编写的页面是一个单窗口 html 工具,我希望两列具有可滚动的内容,并且一个需要反转,因为它是一个日志( other 不太可能滚动,除非故意这样做)。列表和它们的标题也是底部锚定的,我很难让标题保持在弹性可滚动列表的顶部。
感谢上面的示例,我可以弄清楚我缺少什么并获得正确的类类型以使其正常工作。
这是我的full example。在我的实际应用程序中,另外两列左侧有第三列,类为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 的工具,因此非常欢迎 cmets。
【讨论】:
【参考方案18】:基于曼哈顿先生解决方案和 cmets。 https://***.com/a/18614545/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>
【讨论】:
以上是关于除非用户向上滚动,否则保持溢出 div 滚动到底部的主要内容,如果未能解决你的问题,请参考以下文章