3

This speech bubble is used to display error messages on form validation

p.speech {
  position: relative;
  width: 200px;
  height: 40px;
  left: 100px;
  top: 100px;
  background-color: #FFFFFF;
  -webkit-border-radius: 10px;
  -moz-border-radius: 10px;
  border-radius: 10px;
  text-align: center;
  border: 1px solid red;
}
p.speech::before {
  content: ' ';
  position: absolute;
  width: 0;
  height: 0;
  left: -10px;
  top: -10px;
  border: 20px solid;
  border-color: #FF0000 transparent transparent transparent;
  -webkit-transform: rotate(25deg);
  -moz-transform: rotate(25deg);
  transform: rotate(25deg);
}
p.speech::after {
  content: ' ';
  position: absolute;
  width: 0;
  height: 0;
  left: -9px;
  top: -9px;
  border: 19px solid;
  border-color: #FFFFFF transparent transparent transparent;
  -webkit-transform: rotate(25deg);
  -moz-transform: rotate(25deg);
  transform: rotate(25deg);
}
<p class="speech">here is a text</p>

creates a speech bubble, as shown below,

enter image description here

But the pseudo elements have some lines that does not make it transparent.

My question is,

  1. left and top values of pseudo elements show negative values. Why pseudo elements are not positioned based on relative paragraph element? so that the left and top are given positive values?

  2. Why does the pseudo element does not become transparent with after pseudo element?

web-tiki
  • 99,765
  • 32
  • 217
  • 249
overexchange
  • 15,768
  • 30
  • 152
  • 347
  • 2
    These ingenious design hacks keep popping up - Although *quite* amusing, I am starting to doubt about their real-world usefulness since this type of elements can be easily drawn with SVG instead of doing all kinds of crazy hacks. – nicholaswmin Dec 22 '15 at 03:35
  • @overexchange the short answer is just a vector image that looks good on all zoom sizes... worth it to note if you need examples of speech bubbles you can look here; http://nicolasgallagher.com/pure-css-speech-bubbles/demo/ – Daemedeor Dec 22 '15 at 03:37
  • with the amount of time it will take you to make this cross-browser compliant (remember you need to also have control of your bubbles via JS - good luck with attaching events on pseudo elements), it might be better to invest some time in learning SVG instead. – nicholaswmin Dec 22 '15 at 03:38
  • @NicholasKyriakides Sure, I will do that. Thank you for directing me to learn SVG. – overexchange Dec 22 '15 at 03:38
  • 1
    @NicholasKyriakides not that i disagree that SVG is worth learning, doing stuff in CSS3 is also a good exercise as ewll – Daemedeor Dec 22 '15 at 03:38
  • I find them ingenious and an absolutely perfect learning experience - however they don't fare as well as SVG in the wilderness. – nicholaswmin Dec 22 '15 at 03:39
  • So, the above problem is out of clue? At-least answer second question. – overexchange Dec 22 '15 at 03:42
  • This will solve the border problem p.speech::after{ border-right-color: #fff; } – Jinu Kurian Dec 22 '15 at 03:43
  • @NicholasKyriakides Definitely writing such crazy code is hard to maintain – overexchange Dec 22 '15 at 03:44
  • your bubble could be done through css, but have a look and see that you are free to create *ANY* thing you want with SVG, just draw it http://all-free-download.com/free-vector/svg-speech-bubbles.html howmany of them could not be done through css? – Mi-Creativity Dec 22 '15 at 03:48
  • @NicholasKyriakides I think we have `canvas` element also for drawing. How different is that from SVG? – overexchange Dec 22 '15 at 04:02
  • 2
    Completely unnecessary, *for this purpose*. SVG elements can be designed in Adobe Illustrator and just dropped into your site. Furthermore SVG are vector items, thus resolution-independent. Also they are DOM-elements which means that attaching event listeners(`click` etc) on them is just the same as attaching events on any other DOM element (`div`, `input` etc..) - To get the same functionality in canvas you would need to code all this from scratch which is a ridiculous proposition, again, *for the purposes that you need it for*. – nicholaswmin Dec 22 '15 at 04:04

2 Answers2

6

You can do this by creating a single element with a border on two sides and then skew this element to create an arrow instead of a straight corner. Note also the slightly wider (sqrt(2) to be precise) top border, because this one is made more thin by the skewing. The absolute positioning has also been tweaked to make the borders line up.

Note also you should put the message itself in an element and make sure it is in front of the arrow.

Caveat emptor: with thicker border sizes it becomes obvious that the right corner of the arrow has an overshoot into the bubble. As others pointed out it is easy to achieve this with a bit of SVG, which will not have this problem.

p.speech {
  position: relative;
  width: 200px;
  height: 40px;
  left: 100px;
  top: 100px;
  background-color: #FFFFFF;
  -webkit-border-radius: 10px;
  -moz-border-radius: 10px;
  border-radius: 10px;
  text-align: center;
  border: 1px solid red;
}

p.speech::after {
  content: ' ';
  position: absolute;
  width: 20px;
  height: 20px;
  left: 20px;
  top: -11px;
  background: white;
  border-left: 1px solid red;
  border-top: 1.4px solid red;
  -webkit-transform: skew(0, 45deg);
  -moz-transform: skew(0, 45deg);
  transform: skew(0, 45deg);
}

p.speech span {
  position: relative;
  z-index: 1;
}
<p class='speech'>
  <span>Some error text message which is not covered by ::after</span>
</p>
roeland
  • 5,349
  • 2
  • 14
  • 28
1

As other have suggested, SVG would be a good approach for this kind of shape. You can even code it inline with a path element. Here is an example of how you could do it :

p{
  position:relative;
  width:200px;
  height:40px;
  padding: 30px 20px 10px;
  text-align:center;
  z-index:1;
}
svg{
  position:absolute;
  top:0; left:0;
  width:100%;
  height:100%;
  z-index:-1;
}
<p class='speech'>
  <svg width="240" height="80" viewbox="-1 -1 242 82">
    <path d="M40 1 V20 H220 Q240 20 240 40 V60 Q240 80 220 80 H20 Q0 80 0 60 V40 Q0 20 20 20z" 
          fill="transparent" stroke="red" stroke-width="2" />
  </svg>
  Some error text message which is not covered by ::after
</p>
web-tiki
  • 99,765
  • 32
  • 217
  • 249