【问题标题】:height: 100% foils flexbox "stick scrollbar to bottom unless moved"高度:100% 衬托 flexbox “除非移动,否则将滚动条粘贴到底部”
【发布时间】:2019-07-04 17:40:16
【问题描述】:

我有一个类似终端的 contentEditable div。我想要新的输出使其滚动窗口以便它在视图中,除非用户手动移动滚动条以查看另一个位置。在这种情况下,我希望让它查看他们所在的位置。

如果可能的话,我宁愿避免使用 JavaScript 钩子或计时器回调来执行此操作。所以我对使用display: flexflex-direction: column-reverse;a promising CSS-only solution 很感兴趣。 (对该解决方案的评论解释说,您可以通过使用带有属性的外部容器来避免元素反转的麻烦。)

从另一个答案中借用一个 sn-p,这里演示了这种技术在我的浏览器中有效——但仅适用于固定大小的 div

const inner = document.getElementById("inner")
let c = 0

setInterval(function() {
    const newElement = document.createElement("div")
    newElement.textContent = "Line #" + (++c)
    inner.appendChild(newElement)
}, 500)
#outer { /* contents of this div are reversed */
    height: 100px;
    display: flex;
    flex-direction: column-reverse;
    overflow: auto;
}
#inner { /* this div has content in normal order */
}
<div id="outer"><div id="inner"></div></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>

但将其更改为 100% 反而会破坏它。height: auto 也是如此。我可以应用什么魔法来保持行为并使用 100% 的高度?

const inner = document.getElementById("inner")
let c = 0

setInterval(function() {
    const newElement = document.createElement("div")
    newElement.textContent = "Line #" + (++c)
    inner.appendChild(newElement)
}, 500)
#outer { /* contents of this div are reversed */
    height: auto;
    display: flex;
    flex-direction: column-reverse;
    overflow: auto;
}
#inner { /* this div has content in normal order */
}
<div id="outer"><div id="inner"></div></div>
<p>Having changed it to 100%, new content never gets scrolled into view, even if the scroll bar was "stuck" to the bottom</p>

【问题讨论】:

    标签: javascript css flexbox scrollbar


    【解决方案1】:

    对于flexbox,您必须指定它沿 flex-axis 的尺寸(在这种情况下,height 因为它是一个 column flexbox) - 至少它必须继承 intrinsic 宽度 - 请参阅下面的演示,当父元素 #wrap 具有 指定 高度时,它的工作原理:

    const inner = document.getElementById("inner")
    let c = 0
    
    setInterval(function() {
      const newElement = document.createElement("div")
      newElement.textContent = "Line #" + (++c)
      inner.appendChild(newElement)
    }, 500)
    
    function format() {
      return Array.prototype.slice.call(arguments).join(' ')
    }
    #wrap {
      height: 100px;
    }
    #outer {
      /* contents of this div are reversed */
      height: 100%;
      display: flex;
      flex-direction: column-reverse;
      overflow: auto;
    }
    
    #inner {
      /* this div has content in normal order */
    }
    <div id="wrap">
      <div id="outer">
        <div id="inner"></div>
      </div>
      <p>Having changed it to 100%, new content never gets scrolled into view, even if the scroll bar was "stuck" to the bottom</p>
    </div>

    【讨论】:

    • 这是说“不,你不能那样做”吗?我希望我的终端和窗户一样高。我能否以某种方式将其作为纯 CSS 中的固有宽度,或者必须用代码设置它——然后响应窗口调整事件并适当地重置它? (同样,我在这里寻找的是一种“纯 CSS”解决方案,可以解决显示的这方面问题,看起来非常接近。)
    • 是的,你不能那样做...试试 viewport 单位 - vh 而不是 100%? 100vh 如果你想让它和窗户一样高:)
    • 感谢您的建议,但在我的示例中,视口单位似乎没有帮助。更糟糕的是,在我更复杂的示例中——即使高度固定——一旦你移动滚动条,它似乎也不起作用。 :-( 它会一直粘到你这样做,但是一旦滚动条移动它就不会再粘住了。我尝试添加一个滚动条侦听器,它将“捕捉”到绝对底部,但似乎一旦用户有分配了一个意图让它保持它......我看不出有办法回到“默认”状态......并且 Chrome 的调试视图中的dir(document.getElementById(...)) 没有显示特殊的默认设置。
    • @HostileFork, you can't do that in flexbox 是我在这里的意思......这是你链接的一个很好的线程: )
    【解决方案2】:

    使用我在问题中描述的方法,我无法让它工作。请参阅@kukkuz 的回答“你不能这样做...... 在 flexbox 中”,固定大小基本上是它工作的要求。不仅如此,即使保持固定大小,我发现如果您稍微偏离我引用的 sn-p 中的代码,基本示例似乎就失去了坚持到底的能力。

    我发现 确实 的工作是将其倒置(文本倒置,一切),然后将其翻转回外部容器中。该方法是由这个答案提出的:

    https://stackoverflow.com/a/34345634

    这种转换使浏览器认为滚动底部实际上是顶部。固定到顶部比固定到底部更容易(因为它可以建模为常数值 0,而不是不断增长的数字)。

    很奇怪,但它似乎在我尝试过的浏览器中工作!

    【讨论】:

      猜你喜欢
      • 2016-07-29
      • 2012-03-11
      • 1970-01-01
      • 2021-06-26
      • 2023-04-01
      • 2016-04-21
      • 2013-09-07
      • 2019-06-21
      相关资源
      最近更新 更多