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

Having trouble determining whether the Vue project is in debug or release mode in Visual Studio

While developing my Vue app in Visual Studio, I noticed that I keep getting this message in the console regardless of the build mode (debug/release). The message says: "You are running Vue in development mode. Make sure to turn on production mode when ...

How come my variable doesn't show up in the view even though I filled it in the controller?

I'm having trouble with my AngularJS setup. The angular.min.js file is located in the js folder, following a code example from O'Reilly's book. However, for some reason it is not working on my computer. //controller.js function HelloCont ...

Discover the magic of TransformToggle and slideToggle in Javascript, HTML, and CSS

Working on a website coding project and ran into an issue. Trying to utilize an img as a link to slideToggle content. It's working, but I'd like the img to rotate 90deg on the first click and -90deg on the second one. Any solutions are greatly ap ...

"Null" is the value assigned to a JavaScript variable

I am encountering an issue on line 30 with the $.each(data.menu, function (). The console is indicating that "data is null". Can someone clarify what's happening? Thank you! function getFoodMenuData () { var url = 'http://localhost:88 ...

Guide on how to use JavaScript to make an HTML5 input field mandatory

I am facing an issue with setting input fields as required based on radio button selection in a form. Initially, all fields should have required=false, but I'm unable to achieve this. No matter what value I assign to the required attribute, it always ...

The vertical-align property in CSS seems to be malfunctioning

Hi there, I'm struggling with the CSS code below: .parent { position : 'absolute'; top : '50px'; left : '50px'; width : '400px'; height : '160px'; padding : '10px'; ...

Assign the ngClick event handler to the capturing phase

Can the ngClick event handler be configured to work in the capturing phase, as discussed in this informative article? I am interested in stopping events from propagating down to child elements and then back up again when a specific condition is met for t ...

Chrome mistakenly identifying octet-stream as a .png image

My application incorporates the use of Google Maps API V3 and ASP.Net, utilizing OverlayView to customize icons on the map. The icon's image is configured within the onAdd event by dynamically adjusting the background CSS property using JavaScript. T ...

Using AngularJS to dynamically update the DOM with the response from a service method

Here's the HTML code: <div ng-controller="AutoDeployController as autoDeploy"> <input type="text" ng-model="autoDeploy.message"> <p>Message: {{ autoDeploy.message }}</p> </div> <button ng-click="autoDeploy.chan ...

guide on creating a simple line highchart using JSON data

Here is the JSON data I have: {"09/02/2014 15:36:25":[33.82,33.42,40.83],"08/11/2014 16:25:15":[36.6,33.42,40.45],"07/30/2014 08:43:57":[0.0,0.0,0.0],"08/12/2014 22:00:52":[77.99,74.1,80.12],"08/12/2014 21:19:48":[56.91,63.23,52.42],"07/23/2014 13:37:46": ...

Guide to programmatically configuring meta title, description, and image in a Vue.js project with the help of Vue Unhead and Vue Meta

I'm currently developing a Vue.js project where I need to dynamically set the meta title, description, and image based on data fetched from an API. To handle the meta tags, I am utilizing Vue Vue Unhead along with Vue Meta. Below is a snippet of the r ...

The Ultimate Guide for Formatting JSON Data from Firebase

I'm facing an issue with parsing JSON data returned by Firebase. Here is the JSON snippet: { "-JxJZRHk8_azx0aG0WDk": { "email": "<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="cda6a68daaa0aca4a1e3aea2a0">[email&# ...

Utilizing X-editable and Parsley to trigger dual Ajax calls

Here is a snippet of code I am working with: $.fn.editable.defaults.mode = 'inline'; var editable = $('.x-editable').editable({ send: 'always', validate: function() { var form = editable.next().find('form ...

Keep rolling the dice until you hit the target number

Currently, I am in the process of learning JavaScript and one of my projects involves creating a webpage that features two dice images, an input box, and a button. The objective is for users to input a value, click the button, and then see how many rolls i ...

Different from SimplyScroll but with added functionalities

Searching for a replacement for the now deprecated SimplyScroll with specific features. I am in need of a continuous, automatic carousel of boxes/images that halts when hovering over with the mouse (a feature SimplyScroll possesses), and allows movement ...

Creating a specific order for Arabic strings in HTML is simple and can be done by utilizing

I need to adjust the ordering of a datetime written in Arabic numbers. I must use an Arabic string and currently have the following C# code written in Arabic: std.InnerText = "17-02-2016"; The current output is in Arabic numerals, displayed as ٢٠١٦- ...

Issue with React / Express failing to route links accurately

Currently, my React project is functioning well except for Express. I have been struggling to find comprehensive tutorials on implementing correct routing with Express in a MERN stack application. I have come across some Stack Overflow posts, but none of ...

Steps for updating a text section beneath a carousel

I'm looking to enhance my webpage with a bootstrap carousel, which is pretty standard. However, I want the content under each slide to change dynamically, but I'm struggling to make it work. As a newbie, I could use some guidance. I've atte ...

Surround the image with horizontal links on each side

I am attempting to design a horizontal unordered list with an image positioned in the center of it. I am facing the challenge of not being able to insert the image directly within the unordered list. Is there a way to align the image in the center while ha ...

Numerous asynchronous requests

I'm trying to figure out why the application keeps making multiple ajax calls. Check out this directive: gameApp.directive('mapActivity', function() { return { restrict: 'A', link: function(scope, element, att ...