"Mastering the art of crafting chat bubbles similar to those found on Facebook

https://i.sstatic.net/q1zVa.png

Is it possible to create chat bubbles like the ones depicted in the image? Specifically, how can I group two or more consecutive messages from one user into a single bubble? For example, for the sender - the first message has a bottom right border radius of 0, the middle messages have both top and bottom right border radius of 0, and the last message has a top right border radius of 0. Can this be achieved using CSS alone or would JavaScript be required?

The HTML structure could look something like:

<ul>
 <li class="him">By Other User</li>
 <li class="me">By this User, first message</li>
 <li class="me">By this User, second message</li>
 <li class="me">By this User, third message</li>
 <li class="me">By this User, fourth message</li>
</ul>

Which CSS classes/styles should I use to achieve this effect?

Answer №1

This example may seem simple, but it covers all the basic principles you need to understand.

The key solution here involves using the + adjacent sibling selector. It allows you to apply different border radii to consecutive messages from the same sender.

ul{
  list-style: none;
  margin: 0;
  padding: 0;
}

ul li{
  display:inline-block;
  clear: both;
  padding: 20px;
  border-radius: 30px;
  margin-bottom: 2px;
  font-family: Helvetica, Arial, sans-serif;
}

.him{
  background: #eee;
  float: left;
}

.me{
  float: right;
  background: #0084ff;
  color: #fff;
}

.him + .me{
  border-bottom-right-radius: 5px;
}

.me + .me{
  border-top-right-radius: 5px;
  border-bottom-right-radius: 5px;
}

.me:last-of-type {
  border-bottom-right-radius: 30px;
}
<ul>
 <li class="him">By Other User</li>
 <li class="me">By this User, first message</li>
 <li class="me">By this User, secondmessage</li>
 <li class="me">By this User, third message</li>
 <li class="me">By this User, fourth message</li>
</ul>

Answer №2

To achieve the desired result, it is essential to have a start and end class in place. Consider the following example:

li {
  border: 1px solid black;
  list-style-type: none;
  margin: 2px 0;
  padding: 2px 5px;
}
.him {
  float: left;
  border-radius: 0 10px 10px 0;
  clear: both;
}
.me {
  float: right;
  border-radius: 10px 0 0 10px;
  clear: both;
}
.him.start {
  border-top-left-radius: 10px;  
}
.him.end {
  border-bottom-left-radius: 10px;  
}
.me.start {
  border-top-right-radius: 10px;  
}
.me.end {
  border-bottom-right-radius: 10px;  
}
<ul>
 <li class="him start">By Other User</li>
 <li class="him">By Other User</li>
 <li class="him end">By Other User</li>
    
 <li class="me start">By this User, first message</li>
 <li class="me">By this User, secondmessage</li>
 <li class="me">By this User, third message</li>
 <li class="me end">By this User, fourth message</li>

 <li class="him start">By Other User</li>
 <li class="him">By Other User</li>
 <li class="him end">By Other User</li>
    
 <li class="me start">By this User, first message</li>
 <li class="me">By this User, secondmessage</li>
 <li class="me">By this User, third message</li>
 <li class="me end">By this User, fourth message</li>

</ul>

Answer №3

One method to achieve unique styling for the final message of a group in CSS is by applying the chat__bubble--stop class when this message is sent. This solution avoids using the :last-of-type pseudo-class, as it may not accurately identify the last message in a conversation. Instead, it utilizes the adjacent sibling selector (+) to distinguish between messages.

.chat {
  list-style-type: none;
  width: 20em;
}

.chat__bubble {
  margin-bottom: 3px;
  padding: 5px 10px;
  clear: both;
  border-radius: 10px 10px 2px 2px ;
}

.chat__bubble--rcvd {
  background: #f2f2f2;
  color: black;
  float: left;
  border-bottom-right-radius: 10px;
}

.chat__bubble--sent {
  background: #0066ff;
  color: white;
  float: right;
  border-bottom-left-radius: 10px;
}

.chat__bubble--sent + .chat__bubble--sent {
  border-top-right-radius: 2px;
}

.chat__bubble--rcvd + .chat__bubble--rcvd {
  border-top-left-radius: 2px;
}

.chat__bubble--stop {
  border-bottom-right-radius: 10px;
  border-bottom-left-radius: 10px;
}
<ul class="chat">
 <li class="chat__bubble chat__bubble--rcvd chat__bubble--stop">What are you up to?</li>
 <li class="chat__bubble chat__bubble--sent">Not much.</li>
 <li class="chat__bubble chat__bubble--sent">Just writing some CSS.</li>
 <li class="chat__bubble chat__bubble--sent">I just LOVE writing CSS.</li>
 <li class="chat__bubble chat__bubble--sent chat__bubble--stop">Do you?</li>
 <li class="chat__bubble chat__bubble--rcvd">Yeah!</li>
 <li class="chat__bubble chat__bubble--rcvd">It's super fun.</li>
 <li class="chat__bubble chat__bubble--rcvd chat__bubble--stop">... SUPER fun.</li>
</ul>

Answer №4

If you need assistance with creating text bubbles, I recommend checking out this helpful article:

To style the beginning and ending bubbles, utilize JQuery to target and modify their CSS properties within their parent container. In order to display sent images, consider wrapping them in a list item (li) and using float right or absolute positioning inside a relative element.

<ul class="ulContainer">
  <li>test1</li>
  <li>test1</li>
  <li>test1</li>
</ul>

Css:

.ulContainer li {
  width:200px;
  height:20px;
  background-color:#9abff9;
  list-style-type:none;
  margin:10px 0 10px 0;
  padding: 3px 3px 3px 5px;
  border-radius: 10px 2px 2px 10px;
}

Here is the script to style the first and last list items:

$('.ulContainer li:first').css('border-top-right-radius','10px');
$('.ulContainer li:last').css('border-bottom-right-radius','10px');

Check out the JSFiddle example here: https://jsfiddle.net/s60dgfw2/

Update based on your feedback:

For achieving your desired outcome without JQuery, it may require complex selectors that are easier to implement using JQuery. Another option involves adding multiple CSS classes to lists as explained in this response by LGSon.

Alternatively, you can view this example below:

https://jsfiddle.net/5dcto0td/

.fancyContainer{
  border: 1px solid #555;
  position:relative;
  width:300px;
  padding:5px;
  overflow:hidden;
}
.chatBox {
  width: 300px;
  list-style: none;
  margin: 0 0 0 -40px;
  position:0;
}

.chatBox li {
  margin: 5px 0 5px 0;
  padding: 3px 5px 3px 5px;
}

/*Set up initial chat element for .me*/
.chatBox .me {
  min-height: 20px;
  float:right;
  clear: both;
  background-color: #34a1ef;
  border-radius: 10px 2px 2px 10px;
}

/*Set up initial chat element for .him*/
.chatBox .him {
  min-height: 20px;
  float:left;
  clear: both;
  background-color: #ddd;
  border-radius: 2px 10px 10px 2px;
}
/*Set up grouped radius*/
.him + .me {
  border-top-right-radius:10px;
}
.me + .him {
  border-top-left-radius:10px;
}
.me + .me {
  border-bottom-right-radius:2px;
}
.him + .him {
  border-bottom-left-radius:2px;
}


/*Set up First and Last radius for .me*/
.chatBox > .me:first-child {
  border-top-right-radius:10px;
}
.chatBox > .me:last-child{
  border-bottom-right-radius:10px;
}

/*Set up First and Last radius for .him*/
.chatBox > .him:first-child{
  border-top-left-radius:10px;
}
.chatBox > .him:last-child{
  border-bottom-left-radius:10px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="fancyContainer">
  <ul class="chatBox">
    <li class="him">Hello... This is a chatbox.</li>      
    <li class="me">Well well. I guess this is a chatbox.</li>
    <li class="me">I'll have to talk about this some other time.</li>
    <li class="me">No wait. I might change my mind</li>
    <li class="him">Nonesense good sir! We'll have this talk right now and here.</li>
    <li class="him">I Like...</li>
    <li class="him">popsicles.</li>
    <li class="me">I can't believe you've done this to me!</li>
  </ul>
</div>

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

Should buttons be wrapped based on the text of the link?

I'm struggling to include buttons in my design but I can't seem to achieve the desired outcome. The image below illustrates what I am attempting to create but have been unsuccessful in replicating: https://i.sstatic.net/CnYLV.png However, the ...

Unstyled Cards Failing to Receive Design

I am currently working on creating a prototype that utilizes two Bootstrap 4 cards to display information from a form and store related information from another form in the second card. The current layout of this setup can be observed below: https://i.sst ...

Angular Bootstrap dropdown menu opens on the left side for items

When using ngbDropdown, the default alignment of drop down items is on the right side. However, if the drop down alignment is too far to the right, the item may become invisible. Below is the HTML code: <div ngbDropdown class="d-inline-block float_rig ...

Avoid clicking on links while the webpage is still loading

I am facing an issue with my website where I need to intercept link-clicking events using jQuery. Everything works fine, but there is a problem if a user clicks on a link before JavaScript finishes loading, causing it to redirect to another page in error. ...

What is the best way to display the most recent data from a sqlite database and incorporate animations for a more engaging

Hi there! I'm looking to retrieve data from an SQLite database and display only the latest entry. Additionally, I'd like to create an animation where scrolling reveals one entry at a time. I would greatly appreciate any assistance with this. Pl ...

Displaying progress in real-time as the page is being generated using HTML::Mason

For the dynamic web page I'm working on, I have no choice but to use HTML::Mason. However, there is a long computation process involved that affects the loading time. Is there a way to show progress to the user without making Mason wait until the enti ...

Can a line be created using only CSS without the need for an additional HTML element?

There have been many inquiries regarding drawing lines without adding an additional HTML element. Consider this scenario with an HTML div element: <div class="myDiv"></div> Accompanied by the following CSS: .myDiv{ width: 100px; height: ...

What is the process for linking a specific HTML file to a URL?

After preparing all my HTML, CSS, and JS files for upload to a server (I am using cPanel which I have experience with), I found myself wondering how to assign a specific HTML file to a custom link, such as "devwebdevelopment.com/about" I am looking to cre ...

CSS selectors following an ajax request (commenting system)

Issue: After submitting a comment on a webpage, the comments are not displaying correctly. I want them to slide down below the last added comment. It seems to be related to CSS selectors. Can someone help me figure out which selector I need to use? Any a ...

Guide on accessing the text content within a div element in HTML by triggering a button click

To extract specific text from multiple div tags, I need to trigger an event when clicking a button. <div class="col-lg-3 col-md-6 mb-4"> <div class="pricing-table pricing-secondary"> <div class="price-hea ...

Issue with PHP or MySQL not updating the database

I've attempted to post this question twice with no success. I rewrote the script, but now I'm encountering even more issues. Here's the code from my first page: <?php $host="XXXX"; // Host name $username="XXXX"; // Mysql username $pa ...

problem with web page scraping

I'm facing a major issue. My goal is to extract data from a webpage using PHP, but I'm having trouble getting it to work. Specifically, I need to extract the content within the "tr" tags on the page and then parse each text between the "td" tags. ...

Designing a dropdown menu using CSS

Currently, I am facing a requirement to create a menu that should resemble the image provided below. In the past, I have experience working on simple drop-down menus, but this time the specifications are a bit unique. The top menu links should change colo ...

Modify the color of the navigation bar to avoid conflicting with the parallax code

Striving to incorporate a color change in the navbar upon scrolling down has proven to be quite challenging. It seems like there is a conflict between the code for the navbar and the parallax effect on the video canvas placed within a div below it. Upon f ...

Using the power of Selenium's XPath, we can easily navigate through a table to access

Looking for assistance in creating selenium xpath for the various column links within a table. Each row has a unique identifier and contains information about a product, including the name. Based on the product name, I need to locate other links within the ...

Is there a way to ensure consistent heights for various elements within a column, even if their heights are

Currently, I am utilizing the flex property to create uniform columns and vh to ensure they have the same height. This setup is functioning properly, but within each column, there could be a varying number of items. I am interested in having the elements w ...

Breaking an array in JavaScript

I'm developing a pure JavaScript hangman game and facing an issue with splitting words from an array into single letters. When I split the array, I get "," for every letter. For example, when I split the word [station], it returns "s,t,a,t,i,o,n". M ...

Customizing the input field to have a width of 100%

Could someone provide a solution, like a link or working example, for creating input fields with rounded corners that have a width of 100% and a customizable right border? Here is the current structure I am using: <span class="rounded left-corner" ...

JavaScript did not apply the style as expected. However, the console displays the information

Utilizing jQuery to add a specific style $("#notifPrefWA").attr('style', "border-radius: 5px; border:#FF0000 5px solid; padding: 10px;"); The style change is visible in the source and console when Chrome inspected... but the ...

Displaying or concealing HTML elements using AngularJS while a modal is open

Looking for a way to display a loading spinner icon on my page when a user triggers a button that opens a modal, and then have the spinner disappear once the modal is open and its content has loaded. Currently, I've managed to make the spinner show up ...