diff --git a/contents/speech-bubble.mdx b/contents/speech-bubble.mdx
new file mode 100644
index 0000000..09fba85
--- /dev/null
+++ b/contents/speech-bubble.mdx
@@ -0,0 +1,178 @@
+---
+category: Display
+created: '2023-08-31'
+description: Create a speech bubble in CSS
+keywords: css speech bubble
+openGraphCover: /og/css-layout/speech-bubble.png
+thumbnail: /assets/css-layout/thumbnails/speech-bubble.png
+title: Speech bubble
+---
+
+Speech bubbles are a popular and effective way to show dialogue or thoughts in a visual way. You've probably seen them in comics, cartoons, ads, and social media posts. They add humor, emotion, and personality to a design while also giving context to the viewer. Plus, speech bubble layouts can make text-heavy designs more engaging by breaking them up.
+
+In this post, we'll learn how to make a speech bubble layout using CSS. Let's get started!
+
+## Markup
+
+You only need to provide one element to add the speed bubble effect.
+
+```html
+
+
+
+```
+
+## Adding a triangle
+
+To create a speech bubble, we can display a triangle at the bottom-left corner of the container. Rather than adding an external element to the container, we can create the triangle using the `::before` pseudo-element. Here's an example to help you visualize it:
+
+```css
+.speech-bubble {
+ position: relative;
+}
+.speech-bubble::before {
+ content: '';
+
+ position: absolute;
+ bottom: 0;
+ left: -1rem;
+
+ border-width: 1rem;
+ border-style: solid;
+ border-color:
+ transparent transparent rgb(226 232 240) transparent;
+}
+```
+
+First, we set the `position` property of the container to `relative`. This allowed us to position the triangle using absolute positioning.
+
+But the real magic comes from the `::before` pseudo-element. We used the `content` property to add an empty string to this element. That may seem weird, but it's necessary because pseudo-elements require content to be displayed. To position the triangle where we wanted it, we used the `bottom` and `left` properties. By setting the `left` property to a negative value, we moved half of the triangle outside of the container.
+
+Finally, we created the triangle shape by setting the `border-color` property to transparent for the top, left, and right borders. This made the perfect triangle we were looking for.
+
+If you want to change the direction or position of the triangle, it's easy to do by following this [post](https://phuoc.ng/collection/css-layout/triangle-buttons).
+
+Let's take a moment to review the progress we've made with these steps.
+
+
+```css demo.css hidden
+.playground__root {
+ align-items: center;
+ display: flex;
+ justify-content: center;
+ height: 16rem;
+}
+```
+
+```css
+:root {
+ --speech-bubble-background: rgb(226 232 240);
+ --speech-bubble-arrow-size: 1rem;
+}
+.speech-bubble {
+ position: relative;
+
+ background: var(--speech-bubble-background);
+ border-radius: 0.25rem;
+ height: 4rem;
+ width: 12rem;
+}
+.speech-bubble::before {
+ content: '';
+
+ position: absolute;
+ bottom: 0;
+ left: calc(-1 * var(--speech-bubble-arrow-size));
+
+ border-width: var(--speech-bubble-arrow-size);
+ border-style: solid;
+ border-color: transparent transparent
+ var(--speech-bubble-background) transparent;
+}
+```
+
+```html
+
+```
+
+
+## Using two pseudo-elements
+
+In the previous section, we used the `::before` pseudo-element to create a triangle. Now, let's take it a step further and create two circles using the `::before` and `::after` pseudo-elements.
+
+Take a look at the demo below to see how it looks:
+
+
+```css demo.css hidden
+.playground__root {
+ align-items: center;
+ display: flex;
+ justify-content: center;
+ height: 16rem;
+}
+```
+
+```css
+:root {
+ --speech-bubble-background: rgb(226 232 240);
+}
+.speech-bubble {
+ position: relative;
+
+ background: var(--speech-bubble-background);
+ border-radius: 9999px;
+ height: 4rem;
+ width: 12rem;
+}
+.speech-bubble::before,
+.speech-bubble::after {
+ content: '';
+
+ position: absolute;
+ bottom: 0;
+ left: 0;
+
+ border-radius: 9999px;
+ background: var(--speech-bubble-background);
+}
+.speech-bubble::before {
+ height: 1.5rem;
+ width: 1.5rem;
+ transform: translate(-0.5rem, 0.5rem);
+}
+.speech-bubble::after {
+ height: 0.75rem;
+ width: 0.75rem;
+ transform: translate(-1rem, 1rem);
+}
+```
+
+```html
+
+```
+
+
+To achieve this, we position both pseudo-elements absolutely at the bottom-left corner of the container, just like in the previous example.
+
+```css
+.speech-bubble::before,
+.speech-bubble::after {
+ content: '';
+ position: absolute;
+ bottom: 0;
+ left: 0;
+}
+```
+
+However, each of them is positioned differently by using the `transform` property. Let's take a closer look at the `transform` declaration for the `::before` pseudo-element. The first and second numbers move the element along the horizontal (X) and vertical (Y) axis, respectively.
+
+```css
+.speech-bubble::before {
+ transform: translate(-0.5rem, 0.5rem);
+}
+```
+
+## See also
+
+- [Popover arrow](https://phuoc.ng/collection/css-layout/popover-arrow)
+- [Triangle buttons](https://phuoc.ng/collection/css-layout/triangle-buttons)