可滚动的div可以粘到底部,当外部div的大小改变 [英] Scrollable div to stick to bottom, when outer div changes in size
问题描述
以下是聊天应用示例 - >
这里的想法是让 .messages-container
占用尽可能多的屏幕。在 .messages-container
, .scroll
中保存邮件列表,如果有更多邮件,
现在,考虑这种情况:
现在,用户不会滚动到对话底部,而是文本输入增加,而不再看到底部。
一种方法来修复它,如果我们使用react,计算文本输入的高度,如果有任何改变,让.messages-container知道
componentDidUpdate(){
window.setTimeout(_ => {
const newHeight = this.calcHeight();
if !== this._oldHeight){
this.props.onResize();
}
this._oldHeight = newHeight;
});
}
但是,这会导致可见的性能问题,像这样。
有更好的方法吗?我可以使用css以这样的方式,表示当.text-input-increase时,我想基本上上移
所有.messages-container
此答案的第二修订
朋友这里是 flex-direction:column-reverse;
这是所有你要求在消息容器底部对齐消息,就像Skype和许多其他聊天应用程序。
.chat-window {
display:flex;
flex-direction:column;
height:100%;
}
.chat-messages {
flex:1;
height:100%;
overflow:auto;
display:flex;
flex-direction:column-reverse;
}
.chat-input {border-top:1px solid#999; padding:20px 5px}
.chat-input-text {width:60%; min-height:40px; max-width:60%; }
flex-direction:column-reverse;
是IE / Edge / Firefox中的一个错误,滚动条不显示,您可以在这里阅读更多:
上边强大的>你有〜90%的浏览器支持在手机/平板电脑和〜65%的桌面,并计数为bug修复,...有一个解决方法。
//滚动到底部
function updateScroll(el){
el.scrollTop = el.scrollHeight;
}
//只有在底部向上移动
函数scrollAtBottom(el){
return(el.scrollTop + 5> =(el.scrollHeight - el.offsetHeight ));
}
在下面的代码片段中,我添加了上面的2个函数,使得IE / Edge / Firefox的行为方式与 flex-direction:column-reverse;
相同。
div class =snippetdata-lang =jsdata-hide =true>
function addContent(){var msgdiv = document.getElementById('messages'); var msgtxt = document.getElementById('inputs'); var atbottom = scrollAtBottom(msgdiv); if(msgtxt.value.length> 0){msgdiv.innerHTML + = msgtxt.value +'< br />'; msgtxt.value =; } else {msgdiv.innerHTML + ='Long long content'+(tempCounter ++)+'!< br /> } / * if at bottom and is IE / Edge / Firefox * / if(atbottom&&(!isWebkit || isEdge)){updateScroll(msgdiv); }} function resizeInput(){var msgdiv = document.getElementById('messages'); var msgtxt = document.getElementById('inputs'); var atbottom = scrollAtBottom(msgdiv); if(msgtxt.style.height =='120px'){msgtxt.style.height ='auto'; } else {msgtxt.style.height ='120px'; } / * if at bottom and is IE / Edge / Firefox * / if(atbottom&&(!isWebkit || isEdge)){updateScroll(msgdiv); }} / *修复IE / Edge / Firefox * / var isWebkit =(document.documentElement.style中的'WebkitAppearance'); var isEdge =('document.socumentElement.style中的'-ms-accelerator'); var tempCounter = 6 ; function updateScroll(el){el.scrollTop = el.scrollHeight;} function scrollAtBottom(el){return(el.scrollTop + 5> =(el.scrollHeight - el.offsetHeight));}
html,body {height:100%; margin:0; padding:0; } .chat-window {display:flex; flex-direction:column; height:100%;}。chat-messages {flex:1;高度:100%; overflow:auto;显示:flex; flex-direction:column-reverse;}。chat-input {border-top:1px solid#999; padding:20px 5px} .chat-input-text {width:60%; min-height:40px; max-width:60%; } / * temp。演示按钮* / button {width:12%; height:44px; margin-left:5%; vertical-align:top; } / * begin - 修复IE / Edge / Firefox中的隐藏滚动条* /。chat-messages-text {overflow:auto; } @media screen和(-webkit-min-device-pixel-ratio:0){.chat-messages-text {overflow:visible; } / * reset Edge将它自身标识为webkit * / @supports(-ms-accelerator:true){.chat-messages-text {overflow:auto; }}} / *隐藏调整大小FF * / @ - MOZ文档的URL前缀(){.chat输入文本{调整:无}} / *结束 - 修复在隐藏滚动条IE / EDGE /火狐* /
<预类=片段 - 代码HTML语言,HTML prettyprint-覆盖> < DIV CLASS =聊天窗口> < div class =chat-messages> < div class =chat-messages-textid =messages>长长内容1!< br />长长内容2!< br />长长内容3!< br />长长内容4!< br />长长内容5!< br /> < / div> < / div> < div class =chat-input> < textarea class =chat-input-textplaceholder =在此输入您的讯息...id =inputs>< / textarea> < button onclick =addContent();>添加msg< / button> < button onclick =resizeInput();>调整输入大小< / button> < / DIV>< / DIV>
边注1:该检测方法没有完全测试,但它应该在新的浏览器上运行。
边注2:附加调整大小对于聊天输入事件处理可能更有效然后调用updateScroll功能
请注意:贷的危险的重用他的HTML结构
Here is an example chat app ->
The idea here is to have the .messages-container
take up as much of the screen as it can. Within .messages-container
, .scroll
holds the list of messages, and in case there are more messages then the size of the screen, scrolls.
Now, consider this case:
- The user scrolls to the bottom of the conversation
- The
.text-input
, dynamically gets bigger
Now, instead of the user staying scrolled to the bottom of the conversation, the text-input increases, and they no longer see the bottom.
One way to fix it, if we are using react, calculate the height of text-input, and if anything changes, let .messages-container know
componentDidUpdate() {
window.setTimeout(_ => {
const newHeight = this.calcHeight();
if (newHeight !== this._oldHeight) {
this.props.onResize();
}
this._oldHeight = newHeight;
});
}
But, this causes visible performance issues, and it's sad to be passing messages around like this.
Is there a better way? Could I use css in such a way, to express that when .text-input-increases, I want to essentially shift up
all of .messages-container
2:nd revision of this answer
Your friend here is flex-direction: column-reverse;
which does all you ask while align the messages at the bottom of the message container, just like for example Skype and many other chat apps do.
.chat-window{
display:flex;
flex-direction:column;
height:100%;
}
.chat-messages{
flex: 1;
height:100%;
overflow: auto;
display: flex;
flex-direction: column-reverse;
}
.chat-input { border-top: 1px solid #999; padding: 20px 5px }
.chat-input-text { width: 60%; min-height: 40px; max-width: 60%; }
The downside with flex-direction: column-reverse;
is a bug in IE/Edge/Firefox, where the scrollbar doesn't show, which your can read more about here: Flexbox column-reverse and overflow in Firefox/IE
The upside is you have ~ 90% browser support on mobile/tablets and ~ 65% for desktop, and counting as the bug gets fixed, ...and there is a workaround.
// scroll to bottom
function updateScroll(el){
el.scrollTop = el.scrollHeight;
}
// only shift-up if at bottom
function scrollAtBottom(el){
return (el.scrollTop + 5 >= (el.scrollHeight - el.offsetHeight));
}
In the below code snippet I've added the 2 functions from above, to make IE/Edge/Firefox behave in the same way flex-direction: column-reverse;
does.
function addContent () {
var msgdiv = document.getElementById('messages');
var msgtxt = document.getElementById('inputs');
var atbottom = scrollAtBottom(msgdiv);
if (msgtxt.value.length > 0) {
msgdiv.innerHTML += msgtxt.value + '<br/>';
msgtxt.value = "";
} else {
msgdiv.innerHTML += 'Long long content ' + (tempCounter++) + '!<br/>';
}
/* if at bottom and is IE/Edge/Firefox */
if (atbottom && (!isWebkit || isEdge)) {
updateScroll(msgdiv);
}
}
function resizeInput () {
var msgdiv = document.getElementById('messages');
var msgtxt = document.getElementById('inputs');
var atbottom = scrollAtBottom(msgdiv);
if (msgtxt.style.height == '120px') {
msgtxt.style.height = 'auto';
} else {
msgtxt.style.height = '120px';
}
/* if at bottom and is IE/Edge/Firefox */
if (atbottom && (!isWebkit || isEdge)) {
updateScroll(msgdiv);
}
}
/* fix for IE/Edge/Firefox */
var isWebkit = ('WebkitAppearance' in document.documentElement.style);
var isEdge = ('-ms-accelerator' in document.documentElement.style);
var tempCounter = 6;
function updateScroll(el){
el.scrollTop = el.scrollHeight;
}
function scrollAtBottom(el){
return (el.scrollTop + 5 >= (el.scrollHeight - el.offsetHeight));
}
html, body { height:100%; margin:0; padding:0; }
.chat-window{
display:flex;
flex-direction:column;
height:100%;
}
.chat-messages{
flex: 1;
height:100%;
overflow: auto;
display: flex;
flex-direction: column-reverse;
}
.chat-input { border-top: 1px solid #999; padding: 20px 5px }
.chat-input-text { width: 60%; min-height: 40px; max-width: 60%; }
/* temp. buttons for demo */
button { width: 12%; height: 44px; margin-left: 5%; vertical-align: top; }
/* begin - fix for hidden scrollbar in IE/Edge/Firefox */
.chat-messages-text{ overflow: auto; }
@media screen and (-webkit-min-device-pixel-ratio:0) {
.chat-messages-text{ overflow: visible; }
/* reset Edge as it identifies itself as webkit */
@supports (-ms-accelerator:true) { .chat-messages-text{ overflow: auto; } }
}
/* hide resize FF */
@-moz-document url-prefix() { .chat-input-text { resize: none } }
/* end - fix for hidden scrollbar in IE/Edge/Firefox */
<div class="chat-window">
<div class="chat-messages">
<div class="chat-messages-text" id="messages">
Long long content 1!<br/>
Long long content 2!<br/>
Long long content 3!<br/>
Long long content 4!<br/>
Long long content 5!<br/>
</div>
</div>
<div class="chat-input">
<textarea class="chat-input-text" placeholder="Type your message here..." id="inputs"></textarea>
<button onclick="addContent();">Add msg</button>
<button onclick="resizeInput();">Resize input</button>
</div>
</div>
Side note 1: The detection method is not fully tested, but it should work on newer browsers.
Side note 2: Attach a resize event handler for the chat-input might be more efficient then calling the updateScroll function.
Note: Credits to HaZardouS for reusing his html structure
这篇关于可滚动的div可以粘到底部,当外部div的大小改变的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!