JSFiddle - React, Tailwind, and code Playground

by ChangJoo Park

HTML

<div class="wrapper">
  <div class="examples">
    <div class="tooltipped button" data-tooltip-text="<b>비밀글 작성하기</b><br/>비밀글은 작성자 및 언급된 멤버에게만 공개됩니다.<br/>이 설정은 게시 후 다시 수정할 수 있습니다." data-tooltip-position="top">
    </div>
  </div>
</div>

CSS

body {
  margin: 0;
  padding: 0;
}

#container {
  width: 500px;
  height: 30px;
  margin: 0 auto;
  background-color: tomato;
}

.tooltip-wrapper {
  display: inline-block;
  position: relative;
  padding: 5px;
  background-color: #000;
  color: #fff;
  max-width: 320px;
  word-break: break-word;
  border-radius: 5px;
  padding: 10px;
  opacity: 0;
  transform: scale3d(1.0, 1.0, 1.0);
  transition: opacity 0.5s, transform 0.5s;
}

.tooltip-wrapper:after {
  content: '';
  position: absolute;
  border-top: 10px solid #478AF5;
  border-right: 10px solid transparent;
  border-left: 10px solid transparent;
  bottom: -9px;
  left: 50%;
  transform: translateX(-50%);
}

.examples {
  margin-top: 200px;
  text-align: center;
}

.examples .button {
  display: inline-block;
  margin: 10px;
  width: 17px;
  height: 21px;
  background-image: url('https://www.grap.io/files/1487744864170_0f520e01f9077614773a0186585ba99c_rlaehddms1_feed_btn_non_secret.png');
  transition: background-image 0.3s;
}

.examples .button:hover {
  background-image: url('https://www.grap.io/files/1487744864158_0f520e01f9077614773a0186585ba99c_rlaehddms1_feed_btn_secret.png');
  animation-name: heartbeat;
  animation-duration: 0.5s;
}

.fade {
  opacity: 1;
  transform: scale3d(1.05, 1.05, 1.05);
}

@keyframes heartbeat {
  0% {
    transform: scale3d(1,1,1);
  }
  25% {
    transform: scale3d(1.1,1.1,1.1);
  }
  60% {
    transform: scale3d(1.3,1.3,1.3);
  }
  90% {
    transform: scale3d(1.1,1.1,1.1);
  }
  100% {
    transform: scale3d(1,1,1);
  }
}

JavaScript

var targets = document.querySelectorAll('.tooltipped');

targets.forEach(function(target) {
  target.addEventListener('mouseenter', showTooltip);
  target.addEventListener('mouseleave', hideTooltip);
});

function showTooltip(event) {
  var dataset = event.target.dataset;
  var tooltipText = dataset.tooltipText;
  var tooltipPosition = dataset.tooltipPosition || 'bottom';

  var targetRect = event.target.getBoundingClientRect();
  var centerRect = {
    horizontal: targetRect.left + (targetRect.width / 2),
    vertical: targetRect.top + (targetRect.height / 2)
  }

  var tooltipElement = document.createElement('div');
  tooltipElement.className = "tooltip-wrapper"
  tooltipElement.style.backgroundColor = "#478AF5";
  tooltipElement.style.fontColor = "#fff";
  tooltipElement.innerHTML = "<div>" + tooltipText + "</div>";
  tooltipElement.style.position = 'fixed';
  document.body.insertBefore(tooltipElement, document.body.childNodes[0]);

  var tooltipRect = tooltipElement.getBoundingClientRect();
  var tooltipOffset = 5;
  // 포지션 별 위치 조정
  var positionLeft = 0;
  var positionTop = 0;
  switch (tooltipPosition) {
    case 'top':
      positionLeft = (centerRect.horizontal - (tooltipRect.width / 2));
      positionTop = targetRect.top - targetRect.height - tooltipRect.height;
      console.log('positionTop : ', positionTop);
      break;
    case 'bottom':
      positionLeft = (centerRect.horizontal - (tooltipRect.width / 2));
      positionTop = targetRect.bottom + tooltipOffset;
      break;
    case 'left':
      positionLeft = targetRect.left - tooltipRect.width - tooltipOffset;
      positionTop = targetRect.top - (targetRect.height / 2);
      console.log('tooltipRect.height : ', tooltipRect.height);

      break;
    case 'right':
      positionLeft = targetRect.right + tooltipOffset;
      positionTop = targetRect.top - (targetRect.height / 2);
      break;
  }
  if (positionLeft < 0) {
    positionLeft = 0;
  }
  if (positionTop < 0) {
    positionTop = 0;
 ...