首页 > 解决方案 > 我必须添加什么 CSS 来格式化聊天应用程序?

问题描述

我正在尝试设计一个基本的聊天应用程序,没有什么花哨或过分的东西,但我遇到了一些问题。我对造型有三个目标:

  1. 让蓝色消息(您)向右对齐,灰色消息(其他用户)向左对齐。
  2. 让消息在 div 的底部弹出,随后的每条消息都会向上移动一个较旧的消息。
  3. 一旦消息超过像素高度,让 div 滚动。

这是我到目前为止的代码:

const API_URL = "http://localhost:3000"
const form = document.querySelector("form")
const chatbox = document.querySelector(".chatbox")
const chatInput = document.querySelector(".message-input")
const socket = io.connect(API_URL)

socket.on("chat-message", (data) => {
    console.log(data)
    appendMessage("other-message", data)
})

socket.on("disconnect", (reason) => {
    socket.emit("disconnect", reason)
});

form.addEventListener("submit", e => {
    e.preventDefault()
    console.log("message: ", chatInput.value)
    const message = chatInput.value

    appendMessage("message", message)
    socket.emit("send-chat-message", message)
    form.reset()
})

function appendMessage(className, message){
    const div = document.createElement('div')

    div.append(message)
    div.className = className
    chatbox.append(div)
}
.wrapper{
    display: grid;
    grid-template-columns: 1fr 2fr;
    height: 100vh;
    width: 100vw;
}

.side-bar{
    background-color: blue;
    color: gray;
    text-align: left;
    padding: 20px;
    font-size: 50px;
}

.chat-room:hover{
    cursor: pointer;
    color: white;
}

.messages-container{
    display: grid;
    grid-template-columns: auto;  
    grid-template-rows: auto 40px;
}

.chatbox{
    background-color: black;
    border: 1px solid white;
    overflow: scroll;
}

.chatbox > div{
    border-radius: 15px;
    padding: 10px;
    margin: 20px;
    color: white;
    width: fit-content;
    max-width: 50%;
}

.message{
    background-color: blue;
}

.other-message{
    background-color: gray;
}
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <link rel="stylesheet" href="styles.css">
        <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
        <title>chat</title>
    </head>
    <body>
        <div class = "wrapper">
            <div class="side-bar">
                <div class="name">

                </div>
                
                <div class="chat-room"> 
                    <h3>#chat room 1</h3> 
                </div> 
                <div class="chat-room"> 
                    <h3>#chat room 2</h3> 
                </div> 
                <div class="chat-room"> 
                    <h3>#chat room 3</h3> 
                </div> 
                <div class="chat-room"> 
                    <h3>#lifetime chat</h3> 
                </div> 
            </div>

            <div class="messages-container">
                <!-- Chat messages will be appended here! -->
                <div class="chatbox">
                    
                </div>

                <form>
                    <input type="text" class="message-input form-control" required name="send-message" placeholder="Send message" aria-label="Recipient's username" aria-describedby="basic-addon2">
                </form>                
            </div>
        </div>
        
        <script src="https://cdn.socket.io/socket.io-3.0.1.min.js"></script>
        <script src="sendMessage.js"></script>
    </body>
</html>

我目前遇到的问题是,每当我的消息量超过 HTML 文件中“聊天”div 的高度时,div 就不会溢出,而是无限增长。我不确定是什么原因造成的,即使我overflow: scroll;在该特定 div 的 css 中添加了代码。另外,我不确定如何将消息推送到 div 的底部而不是顶部,并让每个新消息将前一个消息向上推送。

我可以使用任何 css 技巧来实现这三个目标吗?

标签: javascripthtmlcsscss-grid

解决方案


CSS Grid 有一个小怪癖,网格子级有一个min-heightmin-width设置为auto. 每当内容超出容器时,这将导致网格拉伸。设置min-height: 0;将防止这种行为并允许发生溢出。阅读此 SO 答案以获取更多详细信息。

我已经为您的chatbox元素添加了一个内部容器。该chatbox元素现在用作溢出包装器。内部元素将是聊天消息的包装。由于您希望消息显示在底部,因此您需要将此内部元素向下推,以便将消息保留在屏幕底部。下推可以用display: grid;和来完成align-items: end;。Flexbox 似乎是一个更好的选择,但它禁用了滚动功能。网格没有。

在内部元素中,使用 Flexbox 将聊天消息定位在左侧或右侧,并以列的形式放置。

最后,在附加每条消息之后,使用chatbox.scrollTo(0, chatbox.scrollHeight)强制chatbox元素在附加到文档的每条消息之后向下滚动。

const API_URL = "http://localhost:3000"
const form = document.querySelector("form")
const chatbox = document.querySelector(".chatbox")
const chatboxInner = document.querySelector(".chatbox-inner")
const chatInput = document.querySelector(".message-input")
const socket = io.connect(API_URL)

socket.on("chat-message", (data) => {
  console.log(data)
  appendMessage("other-message", data)
})

socket.on("disconnect", (reason) => {
  socket.emit("disconnect", reason)
});

form.addEventListener("submit", e => {
  e.preventDefault()
  console.log("message: ", chatInput.value)
  const message = chatInput.value

  appendMessage("message", message)
  socket.emit("send-chat-message", message)
  form.reset()
})

function appendMessage(className, message) {
  const div = document.createElement('div')

  div.append(message)
  div.className = className
  chatboxInner.append(div)
  chatbox.scrollTo(0, chatbox.scrollHeight)
}

// Dummy messages for demo.
setInterval(() => {
  appendMessage('other-message', 'Testing')
}, 4000)
.wrapper {
  display: grid;
  grid-template-columns: 1fr 2fr;
  height: 100vh;
  width: 100vw;
}

.side-bar {
  grid-area: 1 / 1 / 2 / 2;
  background-color: blue;
  color: gray;
  text-align: left;
  padding: 20px;
  font-size: 50px;
}

.chat-room:hover {
  cursor: pointer;
  color: white;
}

.messages-container {
  grid-area: 1 / 2 / 2 / 3;
  display: grid;
  grid-template-columns: 1fr;
  grid-template-rows: 1fr 40px;
  min-height: 0;
}

.chatbox {
  display: grid;
  align-items: end;
  background-color: black;
  border: 1px solid white;
  overflow: scroll;
}

.chatbox-inner {
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  width: 100%;
  padding: 10px 0;
}

.chatbox-inner > div {
  border-radius: 15px;
  padding: 10px;
  color: white;
  width: fit-content;
  max-width: 50%;
}

.chatbox-inner > .message {
  background-color: blue;
  margin: 10px 20px 10px auto;
}

.chatbox-inner > .other-message {
  background-color: gray;
  margin: 10px auto 10px 20px;
}

.as-console-wrapper {
  display: none !important;
}
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <link rel="stylesheet" href="styles.css">
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
  <title>chat</title>
</head>

<body>
  <div class="wrapper">
    <div class="side-bar">
      <div class="name">

      </div>

      <div class="chat-room">
        <h3>#chat room 1</h3>
      </div>
      <div class="chat-room">
        <h3>#chat room 2</h3>
      </div>
      <div class="chat-room">
        <h3>#chat room 3</h3>
      </div>
      <div class="chat-room">
        <h3>#lifetime chat</h3>
      </div>
    </div>

    <div class="messages-container">
      <!-- Chat messages will be appended here! -->
      <div class="chatbox">
        <div class="chatbox-inner">
        
        </div>
      </div>

      <form>
        <input type="text" class="message-input form-control" required name="send-message" placeholder="Send message" aria-label="Recipient's username" aria-describedby="basic-addon2">
      </form>
    </div>
  </div>

  <script src="https://cdn.socket.io/socket.io-3.0.1.min.js"></script>
  <script src="sendMessage.js"></script>
</body>

</html>


推荐阅读