Create a speech bubble using only CSS, featuring a partially see-through background and a stylish border

I wish to design a speech bubble using only CSS.

There are specific requirements I need to meet:

  • It should adjust its size based on content with some padding or a set size.
  • The background color must be semi-transparent.
  • You must be able to define a border, including its level of transparency.
  • Setting a border-radius should affect both the border and background.

Here is an example of how I envision two such speech bubbles looking. The first has a preferred width and height, centered content, while the second adjusts its dimensions based on the content with added padding. The key feature here is that in both cases, the triangular pointer remains the same size and stays centered. https://i.stack.imgur.com/363Zq.jpg

I have explored various approaches for creating speech bubbles and tried customizing examples, such as #34 from here:

// Code snippet...

However, when attempting to set a semi-transparent background color (with a border-radius to mask the overflow behind the border), the triangular point at the bottom does not get filled in. I couldn't find a solution for this issue.

I also came across a similar question here, where I adapted the following code:

<div class="background">
  <div class="bubble">
  <p>
    Hello world! I am some content. Who's got time for lorems?
  </p>
</div>
</div>
.background {
  background: pink;
  display: flex;
  // Other styles...
}

// More CSS code...

But issues arise when introducing semi-transparent colors, causing skewed transforms to overlap and create color discrepancies.

https://i.stack.imgur.com/PQzom.png

Additionally, answers in this post show differing opacity levels between the triangle and the background:

<div class="wrapper">
  <p class="infoBubble">aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa</p>
</div>
.wrapper {
  background: pink;
  // Additional styles...
 }

// More CSS code...

https://i.stack.imgur.com/HkmbM.png https://i.stack.imgur.com/dL8JT.png

So, the final question remains - what is the best approach to achieve the desired results?

Answer №1

Unfortunately, the case you're looking for seems to be missing from my collection. However, we can create it by combining elements #37 and #21. For detailed instructions, visit this link.

To achieve this effect, start by copying the code from element #37. Then, insert an additional span containing the necessary code snippet from element #21 (specifically, the pseudo element part).

.tooltip {
  /* CSS properties here */
}
/* Additional CSS code for the tooltip styling */
<div class="tooltip">
<span></span>
This is a customized tooltip with unique border design and transparent background.</div>

Answer №2

Yes, it can be achieved. Although my code snippet is incomplete, I will provide an explanation of the steps taken so far, allowing you to complete the remaining task.

To create this effect, key properties such as mask, mask-clip, mask-composite, and clip-path were utilized.

The bubble element itself contains a background with its pseudo-element :before expanding 100% in width and height beyond the actual border size. For instance, if the border is 5px, the pseudo-element extends by 10px from all sides (-5px -5px) starting from the top left corner.

The combination of mask, mask-clip, and mask-composite ensures that the background color acts as a border element outside the bubble's boundaries.

Additionally, clip-path is used to carve out space at the bottom for accommodating the arrow placement and also to shape the span:before element into a rectangle mirroring the dimensions of the bubble box.

I hope these insights prove helpful, enabling you to finalize the code yourself. Correcting the clip-path coordinates related to the span:before element should resolve any outstanding issues.

body {padding:0;margin:0;display:grid;min-height:100vh;place-items:center;background:linear-gradient(to bottom right,lightblue,pink);}

.bubble {
  --border: 3px;
  --border-color: rgba(255, 50, 50, .5);
  --background: rgba(0, 0, 0, .5);
  --radius: 1rem;
  --arrow-size: 50px;
  --color: #fff;
  
  position: relative;
  background-color: var(--background);
  max-width: 300px;
  color: var(--color);
  border-radius: calc(var(--radius) - var(--border));
  padding: 1rem;
}
  
.bubble > span {
  position: absolute;
  bottom: 0;
  left: 50%;
  transform: translate(-50%, 50%);
  width: var(--arrow-size);
  aspect-ratio: 1 / 1;
  rotate: 135deg;
  background: var(--background);
  clip-path: polygon(
    var(--border) calc(var(--border) * -1),
    calc(100% + var(--border)) calc(var(--border) * -1),
    calc(100% + var(--border)) calc(100% - var(--border)),
    100% 100%,
    0 0
  );
}
    
.bubble > span:before {
  content: '';
  position: absolute;
  inset: calc(var(--border) * -1);
  border: var(--border) solid transparent;
  mask:
    linear-gradient(transparent, transparent),
    linear-gradient(white, white);
  mask-clip: padding-box, border-box;
  mask-composite: intersect;
  background-color: var(--border-color);
}
  
.bubble:before {
  content: '';
  position: absolute;
  inset: calc(var(--border) * -1);
  border-radius: var(--radius);
  border: var(--border) solid transparent;
  mask:
    linear-gradient(transparent, transparent),
    linear-gradient(white, white);
  mask-clip: padding-box, border-box;
  mask-composite: intersect;
  clip-path: polygon(
    0% 0%, 
    100% 0%, 
    100% 100%, 
    calc(50% + (var(--arrow-size) / 2) + var(--border)) 100%, 
    calc(50% + (var(--arrow-size) / 2) + var(--border)) calc(100% - var(--border)),
    calc(50% - (var(--arrow-size) / 2) - var(--border)) calc(100% - var(--border)),
    calc(50% - (var(--arrow-size) / 2) - var(--border)) 100%,
    0% 100%
  );
  background-color: var(--border-color);
}
<div class="bubble">
  <span></span>
  Lorem ipsum dolor, sit amet consectetur adipisicing elit. Eaque fuga totam repellendus nisi in ea sit quaerat cupiditate, nam, eos aliquam perferendis eligendi, reprehenderit impedit ullam deleniti? Sed, sequi accusamus.
</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

What class is utilized when multiple classes are specified?

When an element has two classes assigned to it and the CSS for the two classes conflict with each other, which one takes precedence? Is there a method to determine which one will be used? For instance: <p class='red small'>Some Text Here& ...

Design of website built on Bootstrap framework seems distorted on Firefox browser

I built this website with the help of Bootstrap and you can view it at js-projects. Everything looks great when I open it in Chrome or Safari, but there are weird white strips that resemble scroll bars when I view it in Firefox. Can someone assist me in ...

Email sending through PHP AJAX can be done without refreshing the page. The email action is handled in email.php and incorporated into

I am having trouble sending this with AJAX. The error message I keep getting is: Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience. For more assistance, please visit @ jquer ...

Sending values from buttons to different Django templates/views

Initially, the user provides a CSV file. (Template File:) <form method="post" action="{% url 'rowcol' %}" enctype="multipart/form-data"> {% csrf_token %} <input type="file" name="file" accept=".csv"> <button type="sub ...

The art of perfect alignment: Mastering the positioning of Material-UI Grid

This issue has been resolved Hey there, I'm currently working on a React App with Material-UI and I'm trying to center a Grid item that includes a Card along with two additional Grid items. Below is the relevant code snippet. Although the Cards ...

What steps are needed to enable the keyboard on a Otree application for mobile devices?

I previously utilized an Implicit Association Task (IAT) in an experiment conducted on computers. However, I now need to adapt this IAT for use on tablets or mobile devices. Here is how the IAT appears on a cellular device: https://i.stack.imgur.com/kNwo ...

Sticky positioning causes elements to stick to the window as the

https://i.stack.imgur.com/nv3vU.png I am facing an issue with a position sticky block that can vary in height relative to the window size. Sometimes, the block is taller than the viewport, making it impossible to scroll to see all the content. Is there a ...

Enhance the appearance of a dropdown selection using CSS

I am interested in customizing the appearance of the first option (Search Clubs) to be bold, while keeping the rest with normal font weight. Currently, I am able to make the first option bold, but it only appears that way after clicking the dropdown menu ...

Hiding Div with JavaScript (Quick and Easy)

Hey there, I'm looking to make regStart and regPage alternate visibility based on a click event. I'm still getting the hang of JavaScript so any simple answers would be appreciated. <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/x ...

What is the best way to send an object to Vue Component?

How can I properly call a Vue Component with a data object? The todo-item tag works as expected, but the todo-item2 tag does not produce any output. I was expecting the same result. Here is the HTML code: <div id="app"> <todo-item v-bind:te ...

In Visual Studio Code, beautification feature splits HTML attributes onto separate lines, improving readability and code organization. Unfortunately, the print width setting does not apply

I have done extensive research and tried numerous solutions, When using Angular and formatting HTML with Prettier, it appears quite messy as it wraps each attribute to a new line, for example: <button pButton class="btn" ...

Eliminating "www" from the domain name leads to a separate website

I am new to this. The lack of support from mediaTemple and my current hosting provider has been frustrating, so I am turning to stackOverflow for help. My issue is that entering "www" before the domain name or leaving it out leads to different servers. ...

Enhancing the appearance of React Native WebView with CSS styling

Currently, I find myself facing a challenge... We are using a WebView in a section of our app because we receive an HTML string from an API endpoint. The HTML styling is not optimized for mobile use, so we are attempting to make some stylistic changes to i ...

How can one address the issue of undefined data within table cells?

I have encountered an issue while reading and displaying an XML file on a webpage using a JavaScript script. The problem arises when the page loads, and the information inside the cells of the table shows as "UNDEFINED". The intended display should include ...

What is the best way to bridge the gap between the rows?

After combining the top and bottom blocks, I now have a gap in my layout. Is there a way to move this row up without causing any issues? I need assistance with resolving this problem using Bootstrap. <link rel="stylesheet" href="https://maxcdn.boots ...

Tips for accessing CSS properties on the img tag

I could use some assistance with CSS. I am in the process of creating a tree structure using many <ul> and <li> tags. The issue arises when I have multiple <li> elements with a specific class, each containing an <img> tag. How can ...

Tips for positioning two fields side by side on a webpage with CSS

I currently have two datepickers aligned vertically and I'm looking to display them in a horizontal layout with some spacing between them. What changes do I need to make in order to present these two calendar pickers side by side on the same row? Cou ...

Retrieve the text content of the paragraph element when its parent is clicked. The paragraph element belongs to a group that contains many

In a function I'm working on, I need to retrieve the specific text within a p element when its parent (.photoBackground) is clicked. The purpose of this operation is to grab the caption for a gallery, where there are multiple p elements with the same ...

Create a custom overlay for an image that is centered horizontally and does not have a fixed width

I'm working with this HTML setup: <div class="container"> <img class="image" /> <div class="overlay"> <div class="insides">more content here</div> </div> &l ...

What is the best way to add permissions to each role in JavaScript?

I have been attempting to dynamically add data to an HTML table using JavaScript. The data consists of roles and their corresponding permissions, which are retrieved using Laravel's ORM. I have tried utilizing a nested each jQuery function to append t ...