除非用户向上滚动,否则将溢出div滚动到底部


222

我有一个只有300像素大的div,我希望它在页面加载时滚动到内容的底部。该div具有动态添加的内容,并且需要一直向下滚动。现在,如果用户决定向上滚动,我不希望它跳回到底部,直到用户再次向下滚动

是否有可能使div保持滚动到底部,除非用户向上滚动,并且当用户滚动回到底部时,即使添加了新的动态内容,它也需要保持在底部。我将如何创建这个。


1
使用css顶部位置,使其位于底部{position : relative; bottom:0;}。用户滚动后,请删除css属性。
TCHdvlp

既然您不接受答案,我想问:它对您有用吗?
曼哈顿先生,2013年

4
听起来像是您想要完成的
聊天框

1
对于这个问题的新手,应该在2020年尝试使用CSS snap
沃纳

Answers:


136

这可能对您有帮助:

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

3
这样可以很好地将其滚动到页面加载的底部,但是添加动态内容时,除非用户向上滚动,否则我需要将其保持在底部。
罗伯特·麦金托什

12
据我所知,当用户滚动到底部时,不会重新启用动态滚动...
TvE 2015年

@TvE不能增加支持吗?
Barkermn01 2015年

6
不好的解决方案。没有理由setInterval为此轻微问题添加一个。
ethancrist

6
@ethancrist但是,您无法选择...耸耸肩。
贾里特·劳埃德

179

我只能使用CSS进行此操作。

诀窍是使用display: flex;flex-direction: column-reverse;

浏览器将底部视为顶部。假设您要定位的浏览器受支持flex-box,唯一的警告是标记必须按相反顺序排列。

这是一个工作示例。https://codepen.io/jimbol/pen/YVJzBg


41
您可以通过添加一个额外的包装器并应用overflow:auto; display:flex; flex-direction:column-reverse;到外部包装器而不是内部包装器来解决内容反转的问题。
内森·亚瑟

6
可能是最好的解决方案,因为它不需要JavaScript。
阿米特·库马尔·卡雷

3
@NathanArthur真正的MVP
php_nub_qq

13
@NathanArthur实际上,如果您只是在容器下添加一个div来撤消所有操作:codepen.io/anon/pen/pdrLEZ
Coo

6
不幸的是,此解决方案似乎无法在Firefox中使用:(
Stuart

166

我只是实现了这一点,也许您可​​以使用我的方法。

假设我们有以下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是top,max是元素的scrollHeight减去元素高度本身。使用滚动条时,将滚动条一直拖到底部可能很困难(对我来说,这是在Chrome中)。所以我加了1px的误差。因此,isScrolledToBottom将真实的,即使滚动条从底部1px的。您可以将其设置为适合您的任何感觉。

然后,只需将元素的scrollTop设置为底部即可。

if(isScrolledToBottom)
    out.scrollTop = out.scrollHeight - out.clientHeight;

我为您展示了这个概念的小提琴:http : //jsfiddle.net/dotnetCarpenter/KpM5j/

编辑:添加了代码片段以澄清何时isScrolledToBottomtrue

将滚动条固定到底部

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>


22
实际上,这是解决上述问题的唯一解决方案。并且应该已经被标记为正确答案。
preezzzy 2015年

1
@dotnetCarpenter:在我看来,您if(!isScrolledToBottom)似乎需要:该测试对我来说似乎是错误的(并且直到我修复它后,该代码才在我的代码中起作用)。
luskwater

1
@luskwater您可以为您提供一个修补程序吗?我不了解的问题out.scrollHeight - out.clientHeight <= out.scrollTop + 1。您是否在CSS中使用填充?
dotnetCarpenter

2
这就是我想要的。并且,这是OP提出的问题的答案。谢谢dotnetCarperter。
路易斯·门吉瓦尔

1
如果有人得到0,当他们打电话scrollTop的,我建议使用document.getScrollingElement如下建议:stackoverflow.com/questions/36227559/scrolltop-always-returns-0/...
戴恩乔丹


14
$('#div1').scrollTop($('#div1')[0].scrollHeight);

Or animated:

$("#div1").animate({ scrollTop: $('#div1')[0].scrollHeight}, 1000);

1
这样可以很好地将其滚动到页面加载的底部,但是添加动态内容时,除非用户向上滚动,否则我需要将其保持在底部。
罗伯特·麦金托什

当div在第一帧中增长很多时,这将不起作用。例如在Angular-js,react js,Meteor Blaze模板加载中,这将不起作用。
索尼

这对我有用。我认为,如果有问题的div保持一致的高度,效果很好。尚未使用动态高度对其进行测试。
doij790

10

在2020年,您可以使用css snap,但是在Chrome 81之前,布局更改不会触发重新快照纯CSS聊天ui可以在Chrome 81上运行,您也可以选中我可以使用CSS snap

该演示将捕捉最后一个元素(如果可见),滚动到底部以查看效果。

.container {
  overflow-y: scroll;
  overscroll-behavior-y: contain;
  scroll-snap-type: y mandatory;
}

.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>

在此处输入图片说明


5

.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>

  1. Run code snippet看效果。(PS:如果Run code snippet不起作用,请尝试以下操作:https : //jsfiddle.net/Yeshen/xm2yLksu/3/

  2. 它是如何工作的:

默认溢出是从上到下滚动。

transform: rotate(180deg) 可以使其从下到上滚动或加载动态块。

  1. 创见:

https://blog.csdn.net/yeshennet/article/details/88880252


请添加更多有关您的代码如何解决OP问题的说明
jro,

1,增加了额外的介绍。2,请Run code snippet,直接看效果。
yisheng wu

运行代码片段按钮对我没有出现。检查格式
jro

那很棒。请在您的答案中包含链接
jro

2
非常有创意的解决方案。但是,它会颠倒鼠标滚轮的正常操作。要向上移动,我必须向下滚动,反之亦然。
mfluehr

3
$('#yourDivID').animate({ scrollTop: $(document).height() }, "slow");
return false;

这将从#yourDivID使用该$(document).height()属性的高度计算ScrollTop位置,以便即使将动态内容添加到div中,滚动条也将始终位于底部位置。希望这可以帮助。但是,即使我们向上滚动并从滚动条上移开鼠标指针,它也会有一个小错误,它将自动到达底部位置。如果有人可以纠正它,那也很好。


2
//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中工作。


2

Jim Hall的答案是可取的,因为当您向上滚动时确实不会滚动到底部,但它也是纯CSS。

但是,非常不幸的是,这不是一个稳定的解决方案:在chrome中(可能是由于上述dotnetCarpenter描述的1像素问题)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的问题。


2

这是基于Ryan Hunt的博客文章的解决方案。它取决于overflow-anchorCSS属性,该属性将滚动位置固定到滚动内容底部的元素。

const messages = [
  'Expect rain today.',
  'Tomorrow will be sunny.',
  'Snow is coming next week.',
  'Hailstorms are imminent.',
];

function addMessage() {
  const $message = document.createElement('div');
  $message.className = 'message';
  $message.innerText = messages[(Math.random() * messages.length) | 0];
  $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或Edge,因此该解决方案当前不适用于所有浏览器。


1

你可以这样使用

var element = document.getElementById("yourDivID");
window.scrollTo(0,element.offsetHeight);

请解释一下!
SzabolcsPáll19年

1.scrollTo是一种将整个窗口滚动到特定坐标的方法2.offsetHeight将提供元素的高度,因此上述代码的第二行在分配某些内容时始终将窗口向下滚动。
Yashesh Chauhan,

0

这是我的处理方法。我的div高度是650px。我决定,如果滚动高度在底部的150px之内,则自动滚动它。否则,将其留给用户。

if (container_block.scrollHeight - container_block.scrollTop < 800) {
                    container_block.scrollTo(0, container_block.scrollHeight);
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.