JSFiddle - React, Tailwind, and code Playground

by Soviut

HTML

<div class="panel">
    <div class="bubble ghost" style="top: 25%; left: 25%;">testing bubble<br/>BR</div>
    <div class="bubble br"    style="top: 25%; left: 25%;">testing bubble<br/>BR</div>
</div>

<div class="panel">
    <div class="bubble ghost" style="top: 25%; left: 25%;">testing bubble<br/>BM</div>
    <div class="bubble bm"    style="top: 25%; left: 25%;">testing bubble<br/>BM</div>
</div>

<div class="panel">
    <div class="bubble ghost" style="top: 25%; left: 25%;">testing bubble<br/>BL</div>
    <div class="bubble bl"    style="top: 25%; left: 25%;">testing bubble<br/>BL</div>
</div>


<div class="panel">
    <div class="bubble ghost" style="top: 25%; left: 25%;">testing bubble<br/>TR</div>
    <div class="bubble tr"    style="top: 25%; left: 25%;">testing bubble<br/>TR</div>
</div>

<div class="panel">
    <div class="bubble ghost" style="top: 25%; left: 25%;">testing bubble<br/>TM</div>
    <div class="bubble tm"    style="top: 25%; left: 25%;">testing bubble<br/>TM</div>
</div>

<div class="panel">
    <div class="bubble ghost" style="top: 25%; left: 25%;">testing bubble<br/>TL</div>
    <div class="bubble tl"    style="top: 25%; left: 25%;">testing bubble<br/>TL</div>
</div>

CSS

* {
    box-sizing: border-box;
}

.panel {
    position: relative;
    width: 480px;
    height: 270px;
    
    background: #CCC;
}

.panel + * {
    margin-top: 10px;
}

.ghost {
    opacity: 0.5;
}

.bubble {
    position: absolute;
    padding: 5px;
    
    background: #FFF;
    text-align: center;
}
.bubble:after {
    content: '';
    position: absolute;
    
    border-style: solid;
    border-width: 10px;
    border-color: transparent;
}

.br {
    -webkit-transform: translate(calc(-100% + 10px + 5px), calc(-100% - 10px));
}
.br:after {
    bottom: -10px;
    right: 5px;
    width: 0;
	height: 0;

	border-top: 10px solid #FFF;
    border-bottom: 0;
}

.bm {
    -webkit-transform: translate(-50%, calc(-100% - 10px));
}
.bm:after {
    bottom: -10px;
    left: 50%;
    width: 0;
    height: 0;
    
	border-top: 10px solid #FFF;
    border-bottom: 0;
    -webkit-transform: translate(-50%, 0);
}

.bl {
    -webkit-transform: translate(calc(0% - 10px - 5px), calc(-100% - 10px));
}
.bl:after {
    bottom: -10px;
    left: 5px;
    width: 0;
    height: 0;
    
	border-top: 10px solid #FFF;
    border-bottom: 0;
}


.tr {
    -webkit-transform: translate(calc(-100% + 10px + 5px), 10px);
}
.tr:after {
    top: -10px;
    right: 5px;
    width: 0;
	height: 0;

	border-top: 0;
    border-bottom: 10px solid #FFF;
}

.tm {
    -webkit-transform: translate(-50%, 10px);
}
.tm:after {
    top: -10px;
    left: 50%;
    width: 0;
    height: 0;
    
	border-top: 0;
    border-bottom: 10px solid #FFF;
    -webkit-transform: translate(-50%, 0);
}

.tl {
    -webkit-transform: translate(calc(0% - 10px - 5px), 10px);
}
.tl:after {
    top: -10px;
    left: 5px;
    width: 0;
    height: 0;
    
	border-top: 0;
    border-bottom: 10px solid #FFF;
}