它可以Flexbox吗?聊天窗口,底部有输入,聊天向上滚动

问题描述 投票:0回答:3

看起来Flexbox应该可以,但我不明白。

http://codepen.io/MichaelJCole/pen/NGBVGe

目标:

  1. 文本区域(用于输入消息)始终位于底部。
  2. 聊天从底部开始,然后根据需要向上滚动。
  3. 如果您使用“Google Hangouts”,例如其中的消息应用程序。

这是标记:

 <div id="chatBar">
    <div id="chatList">
      <div class="chat mine">hello world</div>
      <div class="chat theirs">hello moon</div>
    </div>
    <input id="chatBarInput" class="form-control" type="textarea">
  </div>

这是 CSS:

html, body { height: 100%; }
#chatBar {
  height: 100%;
  display: flex;
  flex-flow: column nowrap;
  justify-content: flex-end;
  overflow: none;
}

#chatList {
  flex: 0 1 auto;
  display: flex;
  flex-flow: column nowrap;
  justify-content: flex-end;
  overflow-y: scroll;
}

#chatBarInput {
  flex: 1 0 auto;
}

.chat {
  flex: none;
  align-self: flex-start;
  background-color: lightgreen;
}

.chat.mine {
  align-self: flex-end;
  background-color: pink;
}

如果不设置高度,我无法让

#chatBar
“挤压”
#chatList
。这就是我试图通过使用 flexbox 来避免的:-/

抱歉,我是后端编码员。尝试了很多东西,然后为 CodePen 进行了精简。

似乎我应该能够告诉内部弹性盒滚动,同时保留外部弹性盒。我必须使用位置:绝对吗?

css flexbox
3个回答
16
投票

如果不设置高度,我无法让#chatBar“挤压”#chatList。 这就是我试图通过使用 flexbox 来避免的事情

您已将所有元素的

flex-basis
设置为
auto
。如果没有明确的高度,Flex 模型将自动尝试通过缩小或扩展元素来容纳可用空间内的所有内容。这就是为什么您无法让
#chatList
按预期工作。
div
本身以及个人聊天都会在可用空间内扩大或缩小。

你应该做的是从简单开始:

#chatBar {
    height: 100%; overflow: hidden;
    display: flex; flex-flow: column;
}
#chatList {
    /* grow or shrink as required from flex-basis height of 20% */
    flex: 1 1 20%; 
    display: flex; flex-direction: column; 
    overflow: auto;
} 

/* do not grow or shrink with a flex-basis height of 80% */
#chatBarInput { flex: 0 0 80%; }

您将能够看到它的工作原理。然后你可以从这里走得更远。

您修改后的codepen:http://codepen.io/Abhitalks/pen/ZbjNvQ/


目标:

  1. 文本区域(用于输入消息)始终位于底部。
  2. 聊天从底部开始,然后根据需要向上滚动。
  3. 如果您使用“Google Hangouts”,例如其中的消息应用程序。

技巧是使用

flex-direction: column-reverse
并将新消息添加到容器中,而不是附加这些消息。

我采用了我的旧答案,并将布局更改为 Flex-model 以实现此目的的演示。您可以仔细阅读代码以了解它是如何完成的。

演示小提琴:http://jsfiddle.net/abhitalks/khj4903t/

演示片段:

var btn 	= document.getElementById('btn'), 
    inp 	= document.getElementById('inp'), 
    chats	= document.getElementById('chatWindow')
;
btn.addEventListener('click', postMsg);

inp.addEventListener('keyup', function(e) {
	if (e.keyCode == 13) { postMsg(); }
});

function postMsg() {
	var msg 	= inp.value,
        bubble 	= document.createElement('div'),
        p 		= document.createElement('p');
    if (msg.trim().length <= 0) { return; }
    bubble.classList.add('bubble');
    bubble.classList.add('right');
    p.textContent = msg;
    bubble.appendChild(p);
    inp.value = '';
    chats.insertBefore(bubble, chats.firstChild);
}
* { box-sizing: border-box; margin: 0; padding: 0; }
html, body { height: 100%; overflow: hidden; }
.wrap { 
    margin: 8px; height: 90%; width: 50%; 
    display: flex; flex-direction: column;
}
.container {
    flex: 1 1 90%; display: flex; flex-direction: column; 
    background-color: #eee; border: 1px solid #ccc; overflow: auto;
}
.form { flex: 0 0 32px; display: flex; border: 1px solid #ddd; }
.form > input[type=text] { flex: 1 1 auto; border: 1px solid #eee; }
.form > input[type=button] { flex: 0 0 20%; border: 1px solid #eee; }
.bubble { flex: 1 1 auto; clear: both; } /* clear the floats here on parent */
.bubble p {
    border-radius: 5px;
    padding: 8px; margin: 8px 12px;
    max-width: 80%;  /* this will make it not exceed 80% and then wrap */
    position: relative; transition: background-color 0.5s; 
}
.left p { background-color: #ccc; float: left; } /* floated left */
.right p { background-color: #33c; color: #fff; float: right; } /* floated right */
/* classes below are only for arrows, not relevant */
.left p::before {
    content: ''; position: absolute;
    width: 0; height: 0; left: -8px; top: 8px;
    border-top: 4px solid transparent;
    border-right: 8px solid #ccc;
    border-bottom: 4px solid transparent;
}
.right p::after {
    content: ''; position: absolute;
    width: 0; height: 0; right: -8px; bottom: 8px;
    border-top: 4px solid transparent;
    border-left: 8px solid #33c;
    border-bottom: 4px solid transparent;
}
<div class="wrap">
    <div id="chatWindow" class="container">
        <div class="bubble left"><p>msg</p></div>
        <div class="bubble left"><p>long message</p></div>
        <div class="bubble right"><p>ultra long message which can wrap at eighty percent </p></div>
        <div class="bubble left"><p>lorem ipsum</p></div>
        <div class="bubble right"><p>very long message</p></div>    
        <div class="bubble right"><p>one more message</p></div>    
        <div class="bubble left"><p>lorem ipsum</p></div>
        <div class="bubble right"><p>another message</p></div>    
        <div class="bubble left"><p>lorem ipsum</p></div>
        <div class="bubble right"><p>yet another message</p></div>    
        <div class="bubble left"><p>lorem ipsum</p></div>
    </div>
    <div id="inputWindow" class="form">
        <input id="inp" type="text" />
        <input id="btn" type="button" value="Send" />
    </div>
</div>


2
投票

浏览器上存在垂直滚动条,因为您已将

height: 100%
设置为
body
,并且 用户代理样式表 将默认的
margin
应用于
body
,通常周围为 8 像素。因此,100% + 16px 启动垂直滚动。

将其添加到您的 CSS 中:

body { margin: 0; }

要将滚动条应用到内部 Flexbox (

.chatlist
),这里有两个调整:

#chatList {
  flex: 0 1 75px; /* specify a height */
  display: flex;
  flex-flow: column nowrap;
  /* justify-content: flex-end; REMOVE */ 
  overflow-y: scroll;
}

演示:http://jsfiddle.net/5p2vy31p/1/


0
投票

这是一种最小的方法,在消息容器上使用

flex: 1 1 auto;
,并在所有父容器上使用
height: 100%
直至文档根。

document.querySelector("form").addEventListener("submit", e => {
  e.preventDefault();
  const input = e.target.querySelector(
    '[name="chat-input-message"]'
  );
  const message = document.createElement("div");
  const messages = document.querySelector(".chat-messages");
  message.textContent = input.value;
  messages.append(message);
  messages.scrollTop = messages.scrollHeight;
  e.target.reset();
});
html, body {
  box-sizing: border-box;
  margin: 0;
  height: 100%;
}

.chat {
  height: 100%;
  display: flex;
  flex-direction: column;
}
.chat-messages {
  padding: 0.3em;
  flex: 1 1 auto;
  overflow-y: scroll;
}
.chat-input {
  display: flex;
}
.chat-input [name="chat-input-message"] {
  width: 100%;
  padding: 0.3em;
}
<div class="chat">
  <div class="chat-messages">
    <div>hello world</div>
    <div>hello moon</div>
  </div>
  <form class="chat-input">
    <input name="chat-input-message">
    <input type="submit">
  </form>
</div>

根据您的用例设计每条聊天消息的样式不应影响布局的其余部分。

© www.soinside.com 2019 - 2024. All rights reserved.