How to make a pseudo element same height and width in pure CSS?

Viewed 503

The .speech height may vary therefore looking for solution to make .speech::after's width same as .speech's height.

ideal result enter image description here

body {
  min-height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;
}

.speech {
  width: 250px;
  padding: 1rem;
  background-color: tomato;
  color: white;
  border: 1px solid;
  position: relative;
}

.speech::after {
  content: '';
  position: absolute;
  top: 0;
  left: 100%;
  border: 3px solid deepskyblue;
  height: 100%;
  padding-left: 50%;
  background: linear-gradient(45deg, transparent 50%, green 0%);
  transform: translateX(-50%) rotate(45deg);
}
<div class="speech">Lorem ipsum dolor sit amet consectetur adipisicing elit. Facilis minima possimus, maxime, fugit dolorum optio, tempora et doloribus doloremque ullam inventore repellendus veniam modi quasi iusto numquam amet eos! Exercitationem.</div>

4 Answers

You don't necessarily need pseudo elements for this, as long as you use CSS gradients, since all browsers that support gradients also support multiple backgrounds:

body {
  min-height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;
}

.speech {
  width: 250px;
  padding: 1rem;
  background: linear-gradient(tomato,tomato),
              linear-gradient(to top right, tomato 49%,transparent 51%),
              linear-gradient(to bottom right, tomato 49%,transparent 51%);
  background-size: calc(100% - 30px) 100%, 30px 50%, 30px 50%;
  background-position: 0 0, 100% 0, 100% 100%;
  background-repeat: no-repeat;
  color: white;
  border: 1px solid;
  position: relative;
}
<div class="speech">Lorem ipsum dolor sit amet consectetur adipisicing elit. Facilis minima possimus, maxime, fugit dolorum optio, tempora et doloribus doloremque ullam inventore repellendus veniam modi quasi iusto numquam amet eos! Exercitationem.</div>

Defining a clip-path will give you the intended result.

The clip-path CSS property creates a clipping region that defines what part of an element should be displayed. Those portions that are inside the region are shown, while those outside are hidden. The clipping region is a path specified either as a URL referencing inline or external SVG, or as a shape, such as a circle().

clip-path - CSS | MDN

var addText = "Lorem ipsum dolor sit amet consectetur adipisicing elit. Facilis minima possimus, maxime, fugit dolorum optio, tempora et doloribus doloremque ullam inventore repellendus veniam modi quasi iusto numquam amet eos! Exercitationem.";

jQuery('.add-text').on('click', function(){
  jQuery('.alt-speech').append(addText);
});
body {
  min-height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;
  flex-direction: column; /* for the sake of demonstration */
}

.speech {
  width: 250px;
  padding: 1rem;
  background-color: tomato;
  color: white;
  border: 1px solid;
  position: relative;
}

.speech::after {
  content: '';
  position: absolute;
  top: 0;
  left: 100%;
  border: 3px solid deepskyblue;
  height: 100%;
  padding-left: 50%;
  background: linear-gradient(45deg, transparent 50%, green 0%);
  transform: translateX(-50%) rotate(45deg);
}

/* Additional */

.alt-speech {
  width: 250px;
  padding: 1rem;
  background-color: tomato;
  color: white;
  border: 1px solid;
  position: relative;
}

.alt-speech:after {
    content: "";
    width: 50%;
    background: tomato;
    -webkit-clip-path: polygon(0 0, 0% 100%, 30% 50%);
    clip-path: polygon(0 0, 0% 100%, 30% 50%);
    top: 0;
    bottom: 0;
    left: 100%;
    position: absolute;
}

.add-text {
    transition: .7s;
    color: white;
    background: tomato;
    padding: 10px 20px;
    cursor: pointer;
}

.add-text:hover {
    background: #c12a0f;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="add-text">Add Text</div>

<div style="margin: 20px 0px"></div>

<div class="alt-speech">Lorem ipsum dolor sit amet consectetur adipisicing elit. Facilis minima possimus, maxime, fugit dolorum optio, tempora et doloribus doloremque ullam inventore repellendus veniam modi quasi iusto numquam amet eos! Exercitationem.</div>

Further Reading:
Creating Responsive Shapes With Clip-Path And Breaking Out Of The Box (Smashing Magazine)

NOTE:
This is an experimental technology, carefully review cross browser compatibility and support before implementing in production.

Cross browser compatibility & support Overview:

  1. caniuse.com
  2. clip-path - CSS | MDN

This is not what you actually asked for. So please correct me if I'am wrong. You asked for a bubble that grows width the height of the parent container. This is not the case with this answer. But I feel this is the desired effect anyways.

Instead of rotating an element by 45% this is using two pseudo elements and linear backgrounds to have a bubble effect.

The width is fixed and may be set according to your needs. But the bubble itself follows the height of any dynamic content.

.speech {
  width: 250px;
  padding: 1rem;
  background-color: tomato;
  color: white;
  border: 1px solid;
  position: relative;
}

.speech::before,
.speech::after {
  content: '';
  position: absolute;
  left: 100%;
  right: 0;
  top: 0;
  width: 45px;
  height: 50%;
}

.speech::before {
  background: linear-gradient(to top right, tomato 50%, transparent 50%);
}

.speech::after {
  top: 50%;
  background: linear-gradient(to bottom right, tomato 50%, transparent 50%);
}
<div class="speech">Lorem ipsum dolor sit amet consectetur adipisicing elit. Facilis minima possimus, maxime, fugit dolorum optio, tempora et doloribus doloremque ullam inventore repellendus veniam modi quasi iusto numquam amet eos! Exercitationem.</div>

<div class="speech">Very small</div>

<div class="speech">
  <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Facilis minima possimus, maxime, fugit dolorum optio, tempora et doloribus doloremque ullam inventore repellendus veniam modi quasi iusto numquam amet eos! Exercitationem.</p>
  <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Facilis minima possimus, maxime, fugit dolorum optio, tempora et doloribus doloremque ullam inventore repellendus veniam modi quasi iusto numquam amet eos! Exercitationem.</p>
</div>

Update your code like this

<!DOCTYPE html>
<html lang="en">

<head>

    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="initial-scale=1.0, maximum-scale=1.0, user-scalable=0, width=device-width;" />
    <meta name="format-detection" content="telephone=no">
    <meta name="description" content="">
    <link rel="shortcut icon" href="favicon.ico" />
    <meta name="author" content="">

    <style>

body {
  min-height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;
}

.speech {
  width: 250px;
  padding: 0px;
  background-color: tomato;
  color: white;
  border: 1px solid;
  position: relative;
}

.speech::after {
  content: '';
  position: absolute;
  width: 0; 
  height: 0;
  top:0px;
  left:100%;

}

</style>
</head>

<body>

<div class="speech">Lorem ipsum dolor sit amet consectetur adipisicing elit. Facilis minima possimus, maxime, fugit dolorum optio, tempora et doloribus doloremque ullam inventore repellendus veniam modi quasi iusto numquam amet eos! Exercitationem. Lorem ipsum dolor sit amet consectetur adipisicing elit. Facilis minima possimus, maxime, fugit dolorum optio, tempora et doloribus doloremque ullam inventore repellendus veniam modi quasi iusto numquam amet eos! Exercitationem.</div>
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<script>
$( document ).ready(function() {
    var ht = $(".speech").height();
    var ht1 = ht/2;
    $("head").append($('<style>.speech:after { border-top: '+ht1+'px solid transparent; border-bottom: '+ht1+'px solid transparent;  border-left: '+ht1+'px solid green;}</style>'));
});
</script>

</body>

</html>
Related