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

Rob*_*osh 180 html javascript css jquery scroll

我有一个只有300像素大的div,当页面加载滚动到内容的底部时我想要它.此div具有动态添加到其中的内容,需要始终保持滚动状态.现在,如果用户决定向上滚动,我不希望它跳回到底部,直到用户再次向下滚动

除非用户向上滚动,当用户向后滚动到底部时,即使添加了新的动态内容,它也需要保持在底部,否则可以使div保持滚动到底部.我该如何创造这个呢?

dot*_*ter 152

我刚刚实现了这个,也许你可以使用我的方法.

假设我们有以下HTML:

<div id="out" style="overflow:auto"></div>
Run Code Online (Sandbox Code Playgroud)

然后我们可以检查它是否滚动到底部:

var out = document.getElementById("out");
// allow 1px inaccuracy by adding 1
var isScrolledToBottom = out.scrollHeight - out.clientHeight <= out.scrollTop + 1;
Run Code Online (Sandbox Code Playgroud)

scrollHeight为您提供元素的高度,包括由于溢出而导致的任何不可见区域.clientHeight为您提供CSS高度或以另一种方式表示元素的实际高度.两种方法都返回高度margin,因此您无需担心.scrollTop为您提供垂直滚动的位置.0是top,max是元素的scrollHeight减去元素高度本身.使用滚动条时,将滚动条一直向下移动可能很困难(我在Chrome中).所以我投入1px不准确.所以,isScrolledToBottom即使滚动条1px的从底部将是真实的.您可以将此设置为适合您的任何内容.

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

if(isScrolledToBottom)
    out.scrollTop = out.scrollHeight - out.clientHeight;
Run Code Online (Sandbox Code Playgroud)

我为你展示了这个概念: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(' ')
}
Run Code Online (Sandbox Code Playgroud)
#out {
    height: 100px;
}
Run Code Online (Sandbox Code Playgroud)
<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>
Run Code Online (Sandbox Code Playgroud)

  • 这实际上是完成所述问题的唯一解决方案.并且应该被标记为正确的答案. (19认同)
  • @dotnetCarpenter:在我看来,好像您需要 `if(!isScrolledToBottom)`:测试对我来说是错误的(并且在我修复它之前无法在 _my_ 代码中工作)。 (2认同)
  • 这就是我想要的.而且,这是OP提出的问题的答案.谢谢dotnetCarperter. (2认同)
  • 也许我很困惑,但不应该是“if (!isScrolledToBottom),”和一个not吗?添加 not 似乎使它能够满足OP的要求。 (2认同)

Jim*_*all 141

我只能使用CSS.

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

浏览器将底部视为顶部.假设您的目标支持浏览器flex-box,唯一需要注意的是标记必须按相反的顺序排列.

这是一个有效的例子.https://codepen.io/jimbol/pen/YVJzBg

  • 您可以通过添加额外的包装器并应用`overflow:auto;来绕过需要反转的内容.显示:弯曲; flex-direction:column-reverse;`到外包装而不是内包装. (32认同)
  • @NathanArthur事实上,如果您只是在容器下添加一个div来取消所有内容:https://codepen.io/anon/pen/pdrLEZ (9认同)
  • 不幸的是这个解决方案似乎在 Firefox 中不起作用:( (8认同)
  • 现在是 2020 年 10 月。我检查过它也可以在 Firefox 上运行。感谢您的快速解决方案。 (7认同)
  • 可能是最好的解决方案,因为它不需要javascript. (6认同)
  • 使用这个,如何在动态添加新内容时滚动到底部?动态添加内容时,这可以正常工作,直到您使用鼠标手动滚动 (4认同)
  • @NathanArthur u da real mvp (3认同)
  • 这个解决方案不会破坏文本选择吗?是从下往上选择。 (3认同)
  • 这很好,但是如果您要动态添加需要从 div 顶部开始的内容,则无济于事。内容将始终开始添加到 div 的底部。示例:https://codepen.io/anon/pen/GMwyej 这里的案例场景,我想是一旦滚动条在 div 上被激活,就始终停留在底部。 (2认同)
  • Dang,我对这个解决方案感到很兴奋,但看起来 FF/Edge/IE 中长期存在的错误 /sf/ask/2397465101/ 将强制使用 JS 解决方案。 (2认同)
  • 很酷的方法!请注意,这会破坏可访问性。要查看这一点,请获取代码片段并将 tabIndex 添加到每个元素,并注意您现在如何按 Tab 键向上移动页面。我想屏幕阅读器也很难以正确的顺序阅读此内容。 (2认同)

Mr.*_*tan 111

虽然这可能会帮助你:

var element = document.getElementById("yourDivID");
element.scrollTop = element.scrollHeight;
Run Code Online (Sandbox Code Playgroud)

[编辑],以匹配评论...

function updateScroll(){
    var element = document.getElementById("yourDivID");
    element.scrollTop = element.scrollHeight;
}
Run Code Online (Sandbox Code Playgroud)

每当添加内容时,调用函数updateScroll(),或设置一个计时器:

//once a second
setInterval(updateScroll,1000);
Run Code Online (Sandbox Code Playgroud)

如果您想仅在用户未移动时更新:

var scrolled = false;
function updateScroll(){
    if(!scrolled){
        var element = document.getElementById("yourDivID");
        element.scrollTop = element.scrollHeight;
    }
}

$("#yourDivID").on('scroll', function(){
    scrolled=true;
});
Run Code Online (Sandbox Code Playgroud)

  • 据我所知,当用户滚动到底部时,这不会重新启用动态滚动... (9认同)
  • 不好的解决方案。对于这个轻微的问题,没有理由添加`setInterval`。 (6认同)
  • @ethancrist然而,你提供了别无选择......耸耸肩. (4认同)
  • 这很好地在页面加载时将其滚动到底部,但是当添加动态内容时我需要它保持在底部,除非用户向上滚动. (3认同)

wen*_*ner 31

在 2020 年,您可以使用css snap,但在 Chrome 81 之前,布局更改不会触发 re-snap纯 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;
}
Run Code Online (Sandbox Code Playgroud)
<div class="container" style="height:6rem">
<div>
<div>1</div>
<div>2</div>
<div>3</div>
<div>4</div>
<div>5</div>
</div>
</div>
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

编辑

使用scroll-snap-type: y proximity;,向上滚动更容易。

  • 接近范围取决于可滚动高度。如果您的聊天视图高于 2 或 3 个聊天气泡,当您向上滚动多达 2 或 3 条消息时,它会再次弹回到末尾(除非您滚动数百个像素),这使得此方法无法使用。共享片段起作用的原因是视图高度太小。 (3认同)
  • @Mohebifar 同意这很难与纯 CSS 一起使用。但是,如果您根据用户在 Javascript 中滚动来打开或关闭 CSS 捕捉,这将成为一个非常令人愉快的解决方案。您不会因为使用 Javascript 管理滚动而感到混乱,同时还可以控制捕捉的敏感度。 (2认同)

Alv*_*aro 25

$('#yourDiv').scrollTop($('#yourDiv')[0].scrollHeight);
Run Code Online (Sandbox Code Playgroud)

现场演示:http://jsfiddle.net/KGfG2/

  • 这很好地在页面加载时将其滚动到底部,但是当添加动态内容时我需要它保持在底部,除非用户向上滚动. (4认同)

Sas*_*ran 13

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

Or animated:

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

  • 这很好地在页面加载时将其滚动到底部,但是当添加动态内容时我需要它保持在底部,除非用户向上滚动。 (2认同)

The*_*ool 13

基于 Jim Halls 的解决方案和评论。/sf/answers/3083598381/

我另外添加了一个元素,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++
    })
  );
Run Code Online (Sandbox Code Playgroud)
.scroll-wrapper {
  height: 100px;
  overflow: auto;
  display: flex;
  flex-direction: column-reverse;
  border: 1px solid black;
}

.scroll-start-at-top {
  flex: 1 1 0%;
}
Run Code Online (Sandbox Code Playgroud)
<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>
Run Code Online (Sandbox Code Playgroud)


yis*_* wu 12

.cont{
height: 100px;
overflow-x: hidden;
overflow-y: auto;
transform: rotate(180deg);
direction:rtl;
text-align:left;
}
ul{
overflow: hidden;
transform: rotate(180deg);
}
Run Code Online (Sandbox Code Playgroud)
<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 Online (Sandbox Code Playgroud)

  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

  • 非常有创意的解决方案。但是,它破坏了鼠标滚轮的正常操作。要向上滚动,我必须“向下”滚动,反之亦然。 (6认同)

mfl*_*ehr 6

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

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);
Run Code Online (Sandbox Code Playgroud)
.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;
}
Run Code Online (Sandbox Code Playgroud)
<section class="scroller">
  <div class="messages">
    <div class="anchor"></div>
  </div>
</section>
Run Code Online (Sandbox Code Playgroud)

请注意,overflow-anchor目前在 Safari 中不起作用。