height: 100% foils flexbox “stick scrollbar to bottom unless moved”

▼魔方 西西 提交于 2020-01-15 04:43:05

问题


I have a terminal-like contentEditable div. I'd like new output to cause it to scroll the window so it is in view, unless the user has manually moved the scroll bar to be viewing another position. In that case, I wish to leave it viewing the position they were at.

I'd prefer to avoid doing this with JavaScript hooks or timer callbacks if at all possible. So I was interested in a promising CSS-only solution of using display: flex with flex-direction: column-reverse;. (A comment on that solution explains that you can avoid the hassle of the reversal of elements by using an outer container with the attribute.)

Borrowing a snippet from another one of those answers, here is a demonstration that this technique works--in my browser--but only for a fixed-size 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>

But changing that to 100% instead breaks it. Same for height: auto. Is there any magic I can apply to keep the behavior and use 100% height?

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>

回答1:


For a flexbox you must specify its dimension along the flex-axis (height in this case as it is a column flexbox) - at least it must inherit an intrinsic width - see demo below where it works when a parent element #wrap has a specified height:

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>



回答2:


I couldn't get this to work using the method I describe in the question. See @kukkuz's answer that "you can't do that... in flexbox", that the fixed size is basically a requirement for it to work. Not only that, but even keeping fixed size I found that the basic example seems to lose its ability to stick to the bottom if you deviate slightly from the code in the snippet I quote.

What I found that did work was to flip it upside down (text upside down, everything), then flip it back in an outer container. The method was suggested by this answer:

https://stackoverflow.com/a/34345634

This transformation makes the browser think the scroll bottom is actually the top. Pinning to the top is easier for it to do than getting pinned to the bottom (since it can be modeled as the constant value 0, as opposed to an ever-growing number).

Pretty weird, but it appears to work in the browsers I've tried!



来源:https://stackoverflow.com/questions/54626982/height-100-foils-flexbox-stick-scrollbar-to-bottom-unless-moved

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!