【问题标题】:Keep overflow div scrolled to bottom unless user scrolls up除非用户向上滚动,否则保持溢出 div 滚动到底部
【发布时间】:2013-09-07 23:42:23
【问题描述】:

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

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

【问题讨论】:

  • 使用css位置顶部保持在底部{position : relative; bottom:0;}。用户滚动后删除 css 属性。
  • 既然你没有接受答案,我想问一下:它对你有用吗?
  • 听起来像是你想要完成的聊天框
  • 对于这个问题的新手,应该在 2020 尝试css snap
  • Here's css-only 方法适用于许多情况。

标签: javascript jquery html css scroll


【解决方案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 &lt;= out.scrollTop + 1 的问题。您是否在 CSS 中使用填充?
  • 这就是我要找的。而且,这就是 OP 提出的问题的答案。谢谢 dotnetCarperter。
  • 也许我很困惑,但它不应该是“if (!isScrolledToBottom)”吗?添加 not 似乎可以满足 OP 的要求。
【解决方案4】:

在 2020 年,您可以使用 css snap,但在 Chrome 81 之前布局更改将 not trigger re-snappure 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>
  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 问题的说明
  • 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/forhireUpwork 向三个人支付了 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>
            

            注意:您可能需要调整scrollToBottomscrollMessages 中的alert 位置(nposxnposy)以满足您的需求...

            还有一个指向我自己的工作示例的链接,托管在我的服务器上: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,用于选择和添加它们或删除顶部元素(即反向列表中底部的 &lt;li&gt; 项)。

                  这里提供了一个较小的版本:

                  <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://stackoverflow.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>

                    【讨论】:

                      猜你喜欢
                      • 2017-07-24
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 2012-03-27
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      相关资源
                      最近更新 更多