Auralinna.blog - Tero Auralinna's web development blogAuralinna.blogTero Auralinna's blog about intriguing world of web development. Tweaking pixels since the '90s.

How to make a CSS speech bubble with borders and drop shadow

Published: 12/22/2017

Here is an example of how to create a CSS speech bubble with borders and drop shadow.

The code snippet at CodePen to play around with chat bubble styles.

Embedded content: https://codepen.io/teroauralinna/pen/JMKyeB

Simple speech bubble

Let's start by creating a simple one with just rounded corners and arrow.

HTML code

We need just one div to create a simple speech bubble. Although <blockquote> is more semantic element in case you're using the bubble for somebody's comment.

<div class="speech-bubble">
  <p><strong>Demo speech bubble</strong></p>
  <p>This is a simple CSS speech bubble.</p>
</div>

SCSS

.speech-bubble {
  background: #efefef;
  border-radius: 4px;
  font-size: 1.2rem;
  line-height: 1.3;
  margin: 0 auto 40px;
  max-width: 400px;
  padding: 15px;
  position: relative;

  p {
    margin: 0 0 10px;

    :last-of-type {
      margin-bottom: 0;
    }
  }

  &::after {
    border-left: 20px solid transparent;
    border-top: 20px solid #efefef;
    bottom: -20px;
    content: "";
    position: absolute;
    right: 20px;
  }
}

Speech bubble with borders and drop shadow

Now we have a base for our speech bubble. Let's add borders and drop shadow next. We need to add a new HTML element for the arrow because we need to simulate borders and drop shadow with other elements.

HTML

Let's add HTML element <div class="speech-bubble-ds-arrow"></div> for arrow.

<div class="speech-bubble-ds">
  <p><strong>Demo speech bubble</strong></p>
  <p>This is CSS speech bubble with borders and drop shadow.</p>
  <div class="speech-bubble-ds__arrow"></div>
</div>

SCSS

CSS is a little bit more complex here because we need to use ::before and ::after pseudo-elements. Class .speech-bubble-ds__arrow will be used for the shadow of the arrow and .speech-bubble-ds-arrow::before will be used for the border. Pseudo-element .speech-bubble-ds__arrow::after will be the arrow.

.speech-bubble-ds {
  background: #efefef;
  border: 1px solid #a7a7a7;
  border-radius: 4px;
  box-shadow: 4px 4px 0 rgba(0, 0, 0, 0.2);
  font-size: 1.2rem;
  line-height: 1.3;
  margin: 0 auto 40px;
  max-width: 400px;
  padding: 15px;
  position: relative;

  p {
    margin-bottom: 10px;

    :last-of-type {
      margin-bottom: 0;
    }
  }
}

.speech-bubble-ds__arrow {
  border-left: 21px solid transparent;
  border-top: 20px solid rgba(0, 0, 0, 0.2);
  bottom: -25px;
  position: absolute;
  right: 15px;

  &::before {
    border-left: 23px solid transparent;
    border-top: 23px solid #a7a7a7;
    bottom: 2px;
    content: "";
    position: absolute;
    right: 5px;
  }
  &::after {
    border-left: 21px solid transparent;
    border-top: 21px solid #efefef;
    bottom: 4px;
    content: "";
    position: absolute;
    right: 6px;
  }
}

You can modify arrow border values or absolute positioning to change arrow size or position.

Be the first commenter?

Latest CodePens

I am an experienced web developer with an eye for solid UI/UX design. I have specialized in front-end development, responsive web design, design systems, modern web frameworks, and content management systems. I also have experience in mobile apps development and back-end coding with PHP, Node.js, and Java. So I have a full stackish background, but I'm enjoying most building robust and beautiful front-ends with performance, accessibility, and testability in mind.

© Tero Auralinna

Auralinna.fiSunset with Bubbles: Travel and Photography Blog

The icon "ellipsis" is provided by loading.io