What specific CSS code do I need to incorporate in order to style a chat application?

I'm currently working on styling a simple chat application, nothing too extravagant, but I'm encountering a few obstacles. My styling goals include:

  1. Aligning blue messages (from you) to the right and gray messages (from other users) to the left.
  2. Displaying messages at the bottom of the div, with each new message pushing the older ones up.
  3. Implementing scroll functionality for the div once the messages exceed a certain height in pixels.

Here's the code I have so far:

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>

I'm currently facing some issues like the div not overflowing when the number of messages exceeds the height specified in the "chat" div in the HTML file. Despite adding the code for overflow: scroll; in the CSS for that specific div, it continues to expand infinitely. Additionally, I'm unsure how to make the messages push to the bottom of the div rather than the top, with each new message displacing the previous one upwards.

Are there any CSS techniques or tricks that could help achieve these three objectives?

Answer №1

To enable the overflow: scroll function, you must explicitly define the height of the div. In this scenario, I utilized calc to set it to 100vh and deducted the form's height.

If you want the scroll to start from the bottom and move upwards, you can utilize element.scrollTo and adjust it to the height of the .chatbox div each time:

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()
  chatbox.scrollTo(0, chatbox.scrollHeight)
})

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 {
  height: calc(100vh - 40px);
  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;
}

input {
  height: 40px;
}
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">


<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>

Answer №2

CSS Grid has an interesting behavior where grid children are given a default min-height and min-width value of auto. This can cause the grid to expand when the content exceeds the container size. To counter this, setting min-height: 0; can prevent the automatic stretching and allow overflow to occur. Check out this Stack Overflow answer for more insights.

I have introduced an inner container within your chatbox element. This inner container now acts as an overflow wrapper, with the actual chat messages housed within it. To ensure the messages display at the bottom, you will need to adjust this inner container's positioning. This can be achieved by using display: grid; and align-items: end;. Although Flexbox might seem like a suitable alternative, it can disable scrolling, whereas Grid does not.

Within the inner element, utilize Flexbox to position chat messages either on the left or right in a column layout.

After appending each message, utilize

chatbox.scrollTo(0, chatbox.scrollHeight)
to automatically scroll the chatbox element down to the most recent message added to the document.

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>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Discovering similarities among array elements by looping through an array

Two sets of arrays have values obtained using the data-attribute(data-product-name). One set contains the full list of available items, while the other set consists of selected items associated with a country. <!-- the item list --> <div ...

What is the suitable condition necessary for optimal functionality?

Greetings all! I am a newbie in the world of development and also new to Stack Overflow. This is my maiden post seeking assistance on the following issue: $(document).ready(function() { $(".header").click(function() { if ($(".header-content"). ...

Exploring the beauty of ASCII art on a webpage

Having trouble displaying ASCII art on my website using a JavaScript function, the output is not as expected... This is how it should appear: https://i.sstatic.net/MCwPb.png And here is the code I am trying to implement for this purpose: function log ...

What is causing the issue with the "Inline-block" property in this CSS code?

Please review the CSS code provided below for styling instructions. /*rex is the container of ex,ex2,ex3*/ div.rex{ height:200px; border:0px; margin:60px auto; padding: 0; vertical-align:top; } div.ex{ width:34%; height:200px; background-color:#4f443a; ...

Having trouble getting smooth scrolling with easing to function properly

I'm facing an issue with a JQuery function that is supposed to enable smooth scrolling using JQuery easing, but for some reason, it's not functioning correctly and I'm unable to pinpoint the error. Here is the code for the function: $(func ...

Issue finding a route based on dates

Hey everyone, I'm working on a feature where I need to fetch tasks made by a user within a specific date range provided by the user. However, I am facing some issues with getting the date and routing it. Here is the URL format that I am trying to work ...

What is the best way to move the numerical range value into a span element?

How can I implement the "update" function to retrieve the current slider value and transfer it to a Meter element with the message "Value: [current value]". The indicator color should be #ffff00 if the current value is at least 85, otherwise, it should b ...

Update the image on a webpage within a template using AJAX code

I manage a website that utilizes templates. Within the template, there is a main image that I need to replace on specific pages, not throughout the entire site. I am seeking a way to change this main image to a new one on select pages using Ajax. Upon re ...

MERN stack: HTML is currently processing while React is failing to compile

I can't seem to figure out why I'm not receiving an error message, but when trying to launch a react app with node, only the Html is being displayed. Am I overlooking something? I've attempted the <script type="text/babel" src=".. ...

In JavaScript, use the following code to replace "(" with "(":

Is there a way to dynamically transform the string "Test(5)" into "Test\(5\)" using JQuery or Javascript? I attempted this approach, but it did not work as expected var str = "Test(5)"; str = str.replace("(","\("); str = str.replace(")"," ...

Tips for updating the border color of a button:

Struggling to alter the border color of a button Attempting borderColor attribute proved futile: borderColor: '#FFFFFF' Anticipated result Code snippet: headerBtn: { backgroundColor: 'black', fontSize: '16px', f ...

Bindings with Angular.js

I have developed an application similar to Pastebin. My goal is to allow users to paste code snippets and display them with syntax highlighting and other visual enhancements, regardless of the programming language used. To achieve this, I utilize Google&ap ...

implement django self,pk post-save success function

It might seem unconventional, but I'm attempting to utilize a primary key (pk) in a success function to generate a href for loading. The pk will be new and generated by the save() method. What I would like to know is how to send the self.pk pack to t ...

What could be causing Express to display a different page than the one specified in res.render?

Upon trying to view the compare.ejs page, I encountered an unexpected issue where a different page was being rendered instead. What could be causing this discrepancy? Here is my app.js code: var compare = require('./routes/compare')(nav); app.u ...

Switch the URL to render the view using Express 4

I am facing an issue with a post request where the views are rendering to /link/123 instead of /anotherlink. Although I could use res.redirect('/anotherlink'), I need to render different data. app.post('/link/:id',function (req, res, n ...

I am looking to update a WordPress site every 10 seconds to keep it current

Currently, I am working on a plugin and my goal is to automatically refresh the widget every 10 seconds. Can someone guide me on how to achieve this? I need to figure out a way to call the widget function at regular intervals in order to refresh the conte ...

What is the best way to determine if a PHP string has identical consecutive letters?

Can you help me figure out why my code isn't working? $pattern_c_sap='/\.\-/'; $local='.................'; $local_array = explode( '', $local ); for($i=0; $i<=$local_length; $i++){ if(preg_match($pattern_c_ ...

What is the method for creating a line break in text?

Here is some example code I have: <h3 class="ms-standardheader"> <nobr> Reasons for proposals selected and not selected </nobr> </h3> Now I also have an image to show. The problem is that my text appears too large, so I a ...

The ID Token could not be verified due to an invalid jwt.split function

I'm currently working on validating a Google ID Token on my Node.js server. Unfortunately, I've encountered the following error: The ID Token cannot be verified: jwt.split is not a function For reference, here is the link to the code that I am ...

Configuring Dialog Placement to the Top in Material-UI

I'm in the process of creating a popup dialog, but I'm encountering an issue where the dialog pops up in the center of the page. How can I position it at the very top of the page when the popup button is clicked? Below is the code snippet: < ...