ツールチップ 実装解説|CSS & JavaScript Tooltip Guide

ツールチップ デザイン見本

要素にホバーまたはクリックしたとき、補足説明を吹き出しで表示する「ツールチップ」の実装パターンを紹介します。CSS単体版とJS版のコピペ用コードを掲載しています。

① CSS のみ — data属性でテキストを指定する

HTML
<button class="tooltip-target" data-tooltip="これがツールチップです">
  ホバーしてみて
</button>
CSS
.tooltip-target {
  position: relative;
  display: inline-block;
}

.tooltip-target::after {
  content: attr(data-tooltip);
  position: absolute;
  bottom: calc(100% + 10px);
  left: 50%;
  transform: translateX(-50%) translateY(4px);
  background: #334155;
  color: #e2e8f0;
  padding: 6px 12px;
  border-radius: 6px;
  white-space: nowrap;
  font-size: 13px;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.2s ease, transform 0.2s ease;
}

.tooltip-target::before {
  content: '';
  position: absolute;
  bottom: calc(100% + 4px);
  left: 50%;
  transform: translateX(-50%);
  border: 6px solid transparent;
  border-top-color: #334155;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.2s ease;
}

.tooltip-target:hover::after {
  opacity: 1;
  transform: translateX(-50%) translateY(0);
}

.tooltip-target:hover::before {
  opacity: 1;
}
content: attr(data-tooltip)

CSSの content: attr(属性名) を使うと、HTMLの属性値を疑似要素のテキストとして表示できます。JavaScriptゼロで実装でき、ツールチップのテキストをHTMLだけで管理できるのが利点です。::before で三角矢印、::after でバルーン本体を作るのが基本構造です。

② 表示方向の切り替え(上下左右)

HTML
<button class="tooltip-target" data-tooltip="ツールチップ" data-dir="top">
  ホバーしてみて
</button>
CSS
.tooltip-target {
  position: relative;
  display: inline-block;
}

.tooltip-target::after {
  content: attr(data-tooltip);
  position: absolute;
  background: #334155;
  color: #e2e8f0;
  padding: 6px 12px;
  border-radius: 6px;
  white-space: nowrap;
  font-size: 13px;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.2s ease, transform 0.2s ease;
}

.tooltip-target::before {
  content: '';
  position: absolute;
  border: 6px solid transparent;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.2s ease;
}

.tooltip-target[data-dir="top"]::after {
  bottom: calc(100% + 10px);
  left: 50%;
  transform: translateX(-50%) translateY(4px);
}
.tooltip-target[data-dir="top"]::before {
  bottom: calc(100% + 4px);
  left: 50%;
  transform: translateX(-50%);
  border-top-color: #334155;
}
.tooltip-target[data-dir="top"]:hover::after { transform: translateX(-50%) translateY(0); }

.tooltip-target[data-dir="bottom"]::after {
  top: calc(100% + 10px);
  left: 50%;
  transform: translateX(-50%) translateY(-4px);
}
.tooltip-target[data-dir="bottom"]::before {
  top: calc(100% + 4px);
  left: 50%;
  transform: translateX(-50%);
  border-bottom-color: #334155;
}
.tooltip-target[data-dir="bottom"]:hover::after { transform: translateX(-50%) translateY(0); }

.tooltip-target[data-dir="left"]::after {
  right: calc(100% + 10px);
  top: 50%;
  transform: translateY(-50%) translateX(4px);
}
.tooltip-target[data-dir="left"]::before {
  right: calc(100% + 4px);
  top: 50%;
  transform: translateY(-50%);
  border-left-color: #334155;
}
.tooltip-target[data-dir="left"]:hover::after { transform: translateY(-50%) translateX(0); }

.tooltip-target[data-dir="right"]::after {
  left: calc(100% + 10px);
  top: 50%;
  transform: translateY(-50%) translateX(-4px);
}
.tooltip-target[data-dir="right"]::before {
  left: calc(100% + 4px);
  top: 50%;
  transform: translateY(-50%);
  border-right-color: #334155;
}
.tooltip-target[data-dir="right"]:hover::after { transform: translateY(-50%) translateX(0); }

.tooltip-target:hover::before { opacity: 1; }
.tooltip-target:hover::after  { opacity: 1; }
data-dir 属性セレクタで方向を分岐する

data-dir="top" のような属性セレクタを使って、方向ごとの配置CSSを切り替えます。上下は left: 50% + translateX(-50%) で水平中央に、左右は top: 50% + translateY(-50%) で垂直中央に揃えます。三角矢印は対応する方向の border-色-color だけを付けることで表現できます。

③ JS版 — クリックで表示・自動消滅(タッチ対応)

HTML
<button class="tt-target" data-tt-text="クリックで表示します">
  クリックしてみて
</button>

<div class="js-tooltip"></div>
CSS
.js-tooltip {
  position: fixed;
  background: #334155;
  color: #e2e8f0;
  padding: 6px 12px;
  border-radius: 6px;
  font-size: 13px;
  white-space: nowrap;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.2s ease;
  z-index: 9999;
}

.js-tooltip.tt-show {
  opacity: 1;
}
JS
(function () {
  var balloon = document.querySelector('.js-tooltip');
  var timer = null;

  function showTip(target) {
    var msg = target.getAttribute('data-tt-text');
    if (!msg || !balloon) return;

    balloon.textContent = msg;

    var rect = target.getBoundingClientRect();
    var tipW = balloon.offsetWidth;
    var viewW = window.innerWidth;
    var rawLeft = rect.left + rect.width / 2;
    var safeLeft = Math.max(tipW / 2 + 8, Math.min(rawLeft, viewW - tipW / 2 - 8));

    balloon.style.left = safeLeft + 'px';
    balloon.style.top  = (rect.top - 40) + 'px';
    balloon.style.transform = 'translateX(-50%)';
    balloon.className = 'js-tooltip tt-show';

    clearTimeout(timer);
    timer = setTimeout(function () {
      balloon.className = 'js-tooltip';
    }, 3000);
  }

  var triggers = document.querySelectorAll('.tt-target');
  for (var i = 0; i < triggers.length; i++) {
    triggers[i].addEventListener('click', function () {
      showTip(this);
    });
  }

  document.addEventListener('click', function (e) {
    var el = e.target;
    var found = false;
    while (el && el !== document.body) {
      if (el.getAttribute && el.getAttribute('data-tt-text') !== null) {
        found = true;
        break;
      }
      el = el.parentElement;
    }
    if (!found) {
      clearTimeout(timer);
      if (balloon) balloon.className = 'js-tooltip';
    }
  });
})();
getBoundingClientRect() で位置を取得する

getBoundingClientRect() は要素のビューポート基準の座標を返します。取得した座標を使って position: fixed のツールチップ要素を配置することで、どんな入れ子構造でも正確な位置に表示できます。ホバーが使えないスマートフォンにも対応できるのがJS版の強みです。

注意点:ツールチップを付ける要素に position: relative を必ず設定してください。また、要素が画面端に近い場合、CSS版では左右のバルーンがはみ出すことがあります。その場合はJS版を使って動的に方向を調整してください。

当サイトで公開しているWebデザインやUIの実装例は、一覧として以下記事に纏めています。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!
目次