ポップオーバー Popover

要素の近くにフローティングで表示される小さなパネル。追加情報やアクションを提供する。

使用場面: ユーザー情報のプレビュー・追加アクション表示・フィルタメニューなど文脈に応じた情報表示 採用例: GitHub, Twitter

ライブデモ

ユーザー情報

山田太郎

フロントエンドエンジニア

東京都在住・5年の経験

ソースコード

<div class="demo-popover-area">
  <div class="demo-popover-wrap">
    <button class="demo-popover-trigger" data-target="demo-pop-1">クリックで表示</button>
    <div class="demo-popover-content" id="demo-pop-1">
      <div class="demo-popover-arrow"></div>
      <div class="demo-popover-header">ユーザー情報</div>
      <div class="demo-popover-body">
        <p><strong>山田太郎</strong></p>
        <p>フロントエンドエンジニア</p>
        <p style="font-size:12px;color:#6b7280;">東京都在住・5年の経験</p>
      </div>
      <div class="demo-popover-footer">
        <button class="demo-popover-action">プロフィールを見る</button>
      </div>
    </div>
  </div>
  <div class="demo-popover-wrap">
    <button class="demo-popover-trigger demo-popover-trigger-outline" data-target="demo-pop-2">アクション</button>
    <div class="demo-popover-content" id="demo-pop-2">
      <div class="demo-popover-arrow"></div>
      <div class="demo-popover-menu">
        <button class="demo-popover-menuitem">&#x270E; 編集</button>
        <button class="demo-popover-menuitem">&#x2398; コピー</button>
        <button class="demo-popover-menuitem demo-popover-menuitem-danger">&#x2716; 削除</button>
      </div>
    </div>
  </div>
</div>
.demo-popover-area { display: flex; gap: 16px; flex-wrap: wrap; padding: 20px 0; align-items: flex-start; justify-content: center; min-height: 250px; }
.demo-popover-wrap { position: relative; display: inline-block; }
.demo-popover-trigger {
  padding: 8px 16px; border: none; border-radius: 8px; font-size: 13px;
  font-weight: 600; cursor: pointer; background: var(--ui-primary); color: #fff;
  transition: opacity 0.2s;
}
.demo-popover-trigger:hover { opacity: 0.9; }
.demo-popover-trigger-outline {
  background: transparent; color: var(--ui-primary);
  border: 2px solid var(--ui-primary);
}
.demo-popover-trigger-outline:hover { background: color-mix(in srgb, var(--ui-primary) 8%, transparent); opacity: 1; }
.demo-popover-content {
  display: none; position: absolute; top: calc(100% + 10px); left: 50%; transform: translateX(-50%);
  background: #fff; border: 1px solid #e5e7eb; border-radius: 12px;
  box-shadow: 0 8px 24px rgba(0,0,0,0.12); z-index: 20; min-width: 200px;
  animation: demo-popover-in 0.2s ease;
}
.demo-popover-content.open { display: block !important; }
@keyframes demo-popover-in { from { opacity: 0; transform: translateX(-50%) translateY(-4px); } to { opacity: 1; transform: translateX(-50%) translateY(0); } }
.demo-popover-arrow {
  position: absolute; top: -6px; left: 50%; transform: translateX(-50%) rotate(45deg);
  width: 12px; height: 12px; background: #fff; border-left: 1px solid #e5e7eb; border-top: 1px solid #e5e7eb;
}
.demo-popover-header { padding: 12px 16px 8px; font-size: 12px; font-weight: 600; color: #6b7280; text-transform: uppercase; letter-spacing: 0.5px; }
.demo-popover-body { padding: 0 16px 12px; font-size: 13px; color: #333; line-height: 1.5; }
.demo-popover-body p { margin: 2px 0; }
.demo-popover-footer { padding: 8px 16px 12px; }
.demo-popover-action {
  width: 100%; padding: 8px; border: none; border-radius: 6px; font-size: 13px;
  font-weight: 600; cursor: pointer; background: var(--ui-primary); color: #fff;
  transition: opacity 0.2s;
}
.demo-popover-action:hover { opacity: 0.9; }
.demo-popover-menu { padding: 6px; }
.demo-popover-menuitem {
  display: block; width: 100%; padding: 8px 12px; border: none; background: none;
  text-align: left; font-size: 13px; color: #333; border-radius: 6px;
  cursor: pointer; transition: background 0.15s;
}
.demo-popover-menuitem:hover { background: color-mix(in srgb, var(--ui-primary) 10%, transparent); color: var(--ui-primary); }
.demo-popover-menuitem-danger:hover { background: #fef2f2; color: #ef4444; }
(function(){
  document.querySelectorAll('.demo-popover-trigger').forEach(function(btn) {
    btn.addEventListener('click', function(e) {
      e.stopPropagation();
      var target = document.getElementById(this.dataset.target);
      var isOpen = target.classList.contains('open');
      document.querySelectorAll('.demo-popover-content.open').forEach(function(p) { p.classList.remove('open'); });
      if (!isOpen) target.classList.add('open');
    });
  });
  document.addEventListener('click', function(e) {
    if (!e.target.closest('.demo-popover-content')) {
      document.querySelectorAll('.demo-popover-content.open').forEach(function(p) { p.classList.remove('open'); });
    }
  });
})();

AIプロンプト

Basic
ポップオーバーをHTML/CSS/JSで作ってください。ボタンをクリックするとフローティングパネルが表示されます。
Custom
以下の仕様でポップオーバーを実装してください。
- クリックで表示/非表示の切り替え
- 矢印付きのフローティングパネル
- プライマリカラー: #2563eb
- ヘッダー・ボディ・フッター構成
- 外側クリックで閉じる
- フェードイン/アウトアニメーション
- メニュー型のバリエーション(アクションリスト)
Advanced
アクセシビリティ対応のポップオーバーを実装してください。
- aria-expanded / aria-haspopup / aria-controls の適切な設定
- Escapeキーで閉じる
- フォーカストラップ(ポップオーバー内でTabキーが循環)
- Floating UI ライクな自動位置調整(画面端でフリップ)
- ネスト対応(ポップオーバー内にポップオーバー)
- ホバー表示モードのオプション
- prefers-reduced-motion 対応
- スクリーンリーダーで内容の読み上げ対応