JSFiddle - React, Tailwind, and code Playground

by Adambasszer

HTML

<button onclick="moveBubbleToId('1')">moveBubbleTo1</button>
<button onclick="moveBubbleToId('2')">moveBubbleTo2</button>
<button onclick="moveBubbleToId('3')">moveBubbleTo3</button>
<button onclick="moveBubbleToId('4')">moveBubbleTo4</button>
<button onclick="moveBubbleToId('5')">moveBubbleTo5</button>
<button onclick="moveBubbleToId('6')">moveBubbleTo6</button>
<button onclick="moveBubbleToId('7')" id="7">justaButton</button>

<p id="1">11111111</p>
<p id="2">22222</p>
<p id="3">333333</p>
<p id="4">444444</p>
<p id="5">5555555</p>
<div id="6"><p id="1">11111111</p>
<p id="2">22222</p>
<p id="3">333333</p>
<p id="4">444444</p>
<p id="5">5555555</p> images or additional markupThis speech bubble is created entirely with CSS, without any images or additional markupThis s</div>
<div id="speechBubble" class="speech-bubble">This speech bubble is created entirely with CSS, without anely with CSS, without any images or additional markupThis speech bubble is created entirely with CSS, without any images or additional markupThis speech bubble is created entirely with CSS, without any images or additional markupThis speech bubble is created entirely with CSS, without any images or additional markupThis speech bubble is created entirely with CSS, without any images or additional markupThis speech bubble is created entirely with CSS, without any images or additional markupThis speech bubble is created entirely with CSS, without any images or additional markup.</div>

CSS

.speech-bubble
  {
   width: 200px;
   padding: 10px;
   background: #404040;
   color: #fff;
   font: normal 12px "Segoe UI", Arial, Sans-serif;
   -moz-border-radius: 10px;
   -webkit-border-radius: 10px;
   border-radius: 10px;
    position: absolute;
    visibility:hidden;
  }
  .speech-bubble:after
  {
   content: "";
   border: solid 10px transparent; /* set all borders to 10 pixels width */
   border-top-color: #404040; /* the callout */
   border-bottom: 0; /* we do not need the bottom border in this case */
   width: 0;
   height: 0;
   overflow: hidden;
   display: block;
   position: relative;
   bottom: -20px; /* border-width of the :after element + padding of the root element */
    left: -90px;
   margin: auto;
  }

JavaScript

var getCumulativeOffset = function (obj) {
    var left, top;
    left = top = 0;
    if (obj.offsetParent) {
        do {
            left += obj.offsetLeft;
            top  += obj.offsetTop;
        } while (obj = obj.offsetParent);
    }
    return {
        x : left,
        y : top
    };
};

function moveBubbleToXY(left, top){
    var bubble = document.getElementById('speechBubble');
    bubble.style.top = top;
    bubble.style.left = left;
}

function moveBubbleToId(id){
    var node = document.getElementById(id);
    var position;
    var bubble = document.getElementById('speechBubble');
    var p = document.createElement("p");
    bubble.style.visibility = "visible";
    node.appendChild(p);
    position = getCumulativeOffset(p);
    bubble.style.top = position.y + "px";
    bubble.style.left = position.x + "px";
    console.log("x: " + position.x + " y: " + position.y);
}




var xy = getCumulativeOffset(document.getElementById('1'));

console.log(document.getElementById('1'));
var asdfj = getCumulativeOffset(document.getElementById('1'));
console.log(asdfj.y);