Designing a layout for a chat application that is structured from the bottom up

I'm currently in the process of designing a web application for a chat platform. I have access to an API that provides a list of messages:

chatsite.com/api/thread/1/messages/

[
    {
        "id": 2,
        "sender": {
            "id": 2,
            "email": "<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="81f4f2e4f3f5f6ec1e6ece0e8edafe2eeec">[email protected]</a>"
        },
        "sent_datetime": "2017-09-06T17:31:30Z",
        "body": "user two sending a message in new thread (pk1)"
    },
    {
        "id": 1,
        "sender": {
            "id": 1,
            "email": "<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="433630263103242e222a2f6d202c2e">[email protected]</a>"
        },
        "sent_datetime": "2017-09-06T17:28:56Z",
        "body": "New thread test body"
    }
]

This is how the current HTML is structured:

<div id="Thread">
    <div id="Header"></div>
    <div id="MessageList">
        <div class="message">
            <p>{{message.body}}</p>
        </div>
        <div class="message">
            <p>{{message.body}}</p>
        </div>
        <div class="message">
            <p>{{message.body}}</p>
        </div>
    </div>
    <div id="Footer"></div>
</div>

Below is the related CSS styling:

#Thread {
    background-color: mediumseagreen;
    display: flex;
    flex-direction: column;
    overflow-y: hidden;
    height: 600px;
}

#Header {
    height: 100px;
    background-color: blueviolet;
}

#MessageList {
    background-color: deepskyblue;
    height: 100%;
    display: flex;
    flex-direction: column;
    overflow-y: auto;
}

.message {
    background-color: white;
    padding: 8px;
    border: 1px solid #f9f9f9;
    font-size: 30px;
    margin: 4px;
}

#Footer {
    height: 100px;
    background: red;
}

Currently, the messages are displayed from top to bottom with the latest message at the top. However, I would like to reverse this order and display the messages from bottom to top:

__________________
|                |
|     HEADER     |
|________________|
|                |
| Latest Message |
|________________|
|                |
| 2nd Latest Message |
|________________|
|                |
|                |
|                |
|                |
|________________|
|                |
|     FOOTER     |
|________________|

To achieve this layout change, I plan on utilizing Vue.js as my frontend framework.

Answer №1

Simply update the code snippet from:

#MessageList {
    flex-direction: column;
}

to

#MessageList {
    flex-direction: column-reverse; /* this */
}

#Thread {
  background-color: mediumseagreen;
  display: flex;
  flex-direction: column;
  overflow-y: hidden;
  height: 100vh;
}

#Header {
  height: 25px;
  background-color: blueviolet;
}

#MessageList {
  background-color: deepskyblue;
  height: 100%;
  display: flex;
  flex-direction: column-reverse;
  overflow-y: auto;
}

.message {
  background-color: white;
  padding: 4px;
  border: 1px solid #f9f9f9;
  font-size: 1rem;
  margin: 4px;
}

#Footer {
  height: 100px;
  background: red;
}
<div id="Thread">
  <div id="Header"></div>
  <div id="MessageList">
    <div class="message">
      <p>Latest</p>
    </div>
    <div class="message">
      <p>Older</p>
    </div>
    <div class="message">
      <p>Oldest</p>
    </div>
  </div>
  <div id="Footer"></div>
</div>

Answer №2

setInterval(function () {
  var main = document.querySelector('main');
  var div = document.createElement('div');
  div.textContent = Date();
  main.appendChild(div);
  main.scrollTop = main.scrollHeight; // This may increase the size, but the browser will manage it
}, 1000);
html, body {
  height: 100%;
  margin: 0;
}

body {
  display: flex;
  flex-direction: column;
}

main {
  flex: 1 1 auto;
  overflow: auto;
  background: antiquewhite;
  display: flex;
  flex-direction: column;
}

main::before {
  content: "";
  flex: 1 0 0px;
}
<header>Header</header>
<main></main>
<footer>Footer</footer>

Answer №3

To ensure the last message stays at the bottom of the container, you can reverse the flow and scrollbar using the CSS properties:

flex-direction:column-reverse; transform:scale(1,-1);

An additional wrapper was added due to a bug where flex-direction:column + flex:1 + overflow:auto was not functioning as expected. This extra wrapper provides an efficient scrollbar for scrolling to older messages if needed, with the last one displayed at the bottom near the footer.

For example:

Click here for a CodePen demo

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

How can I use `app.js` in Zendesk to connect to an external API using the complete URL

As someone new to developing Zendesk apps, I've been following the step-by-step guide available here. To Summarize I'm facing an issue with passing external API URLs to the AJAX call syntax within Zendesk's app.js file. You can find my sim ...

Saving the output of an AngularJS expression in an input field

Looking at the calculations below, I am currently evaluating an expression, {{ annualIncome * 4.5 }}, in one input and then re-evaluating the same expression in another input. Instead of saving the result and transferring it to the other input, I am repeat ...

Encountering an _FSEventStreamCreate error while setting up Vue3 installation

After using Vue2 for my studies, I decided to make the switch to Vue3. I started by uninstalling Vue2 on my Mac: npm uninstall vue-cli -g Next, I installed Vue3: npm install -g @vue/cli Upon checking the Vue version, I found it to be: (base) Tims-iMac-Pr ...

Adjust the CSS of the currently dragged item using jQuery sortable

I am currently using jQuery-ui sortable and facing an issue with changing the appearance of a dragged item. I would like the text value of the component inside the red background container to be displayed while dragging. Can someone please assist me with t ...

What are the recommended callbacks for initiating ajax calls and managing files/chunks during dropzone chunk uploading?

I am currently working on implementing chunk uploading using dropzone js and php. My main concern is regarding the placement of ajax calls in this process. When dealing with single file uploads, specifying the URL parameter is sufficient. However, when ...

The Vue 2 watch feature may encounter difficulties with mixin data properties, however, it functions properly when the data property belongs to the

I recently attempted to refactor some code by moving certain functionalities to a vue mixin from the component itself, with the intention of reusing it in multiple components. The simplified version of the code looks like this: export default { data() { ...

Avoid using `@typescript-eslint/no-floating-promises` when using a `const` function

Can anyone help me understand why the @typescript-eslint/no-floating-promises rule works with some async functions but not all? To my understanding, these two functions should be equivalent: const getUser = async (userId: string): Promise<User> => ...

Display outcome prior to completion of the website processing in http/html/ajax

I am currently exploring ways to display a wait message in a web application while a task is running for an extended period of time. I am struggling with whether it is even possible. The issue seems to be that the website will only return to the user&apos ...

Refreshing Rails Views by Periodically Polling the Database

We are currently developing a statusboard to monitor all our external servers. Our database contains information about OS, software versions, and other details that are subject to frequent updates. To ensure real-time visibility of these changes on the web ...

Tips for confirming schedule accuracy

Trying to determine if a specific time falls between two others is the task at hand. Allow me to illustrate: Presently, it's Thursday, and the time reads 11:39 PM. Establishment X operates from 12:00 AM to 11:59 PM on Thursdays (a regular occurrence ...

Accessing content from a different HTML document

I'm currently working on a project using node.js where I need to take input from a text box in an HTML file and store it in an array. However, I'm struggling with how to achieve this. My ultimate aim is to create a chat application, and I believe ...

I only notice certain text after carefully inspecting the elements in Google Chrome

While creating an application on Sitefinity (ASP.NET), I encountered an issue where certain elements, such as button text and labels, were not loading correctly when running the application. However, upon inspecting the element, they appeared to be working ...

Guide on adding pictures to an ExpressJS server

Working on this project has been quite a challenge for me as I delve deeper into web development. As a relatively new developer, creating a one-page application with image upload functionality has proven to be quite the task, especially considering this is ...

Dynamic horizontal div elements laid out in a repeating pattern using CSS Grid

I'm fairly new to CSS/Html/JS and I'd like to create a row of Boxes (loaded from a json file) displayed horizontally. Something similar to this: Here's the code snippet I've been using: <style> .wrapper { display: grid; ...

Displaying HTML with AngularJS dynamic data-binding

Here is a sample view: <div ng-show=""> <div style='background-color: #13a4d6; border-color: #0F82A8'> {{headerdescription}} <div style='float: right'>{{price}} $</div> </div> <div style=&apos ...

When implementing tooltips in Apexchart's JavaScript, the y-axis second does not appear in the chart

Typically, when I append data to the second y-axis as an array, it works perfectly. However, for some reason, when I try to append a collection to the data, it no longer shows with two y-axes simultaneously. I even tried adding x and y as the Apex documen ...

Manipulate Attributes in Javascript

Having an issue here - I'm trying to use JavaScript to set some attributes. for(i=0;i<div_navi.childNodes.length;i++){ if(div_navi.childNodes[i].nodeName =="SPAN"){ div_navi.childNodes[i].setAttribute("onclick","g ...

Select values to Component from an array contained within an array of objects

Each user possesses a unique list of tags, and every item owned by the user can be associated with multiple tags from this list. In this scenario, I am attempting to display all the tags belonging to a user for a particular item. If the item has a tag tha ...

The select event in Vuetify's v-select component does not fire when clicking on an option with a custom

Currently, I am utilizing the beta version of Vuetify (v3.0.0-beta.6) due to the necessity of using Vue 3 which is not compatible with Vuetify 2.x. My objective is to create an i18n selector featuring country flag icons. For managing i18n functionalities ...

Unable to select the initial element

Having trouble targeting the first child in this code snippet. I've tried various methods but nothing seems to be working. Any suggestions on how to resolve this? <div id="main"> <div class="page"> <p>random 1</p> </div ...