本文へスキップ

コンテキストメニュー

ステージ上を右クリック(長押し)すると、カーソル位置にメニューが開く。アイコン付き項目・区切り線・破壊的項目を持ち、項目クリック・外側クリック・Escで閉じる。

プレビュー

クリック

操作クリック/タップで動きます。

仕様書

向く場面
  • 右クリックで対象に紐づく操作を出す
  • 行・カードごとの編集/複製/削除
  • スマホの長押しメニュー
避ける場面
  • 主要な操作の唯一の入口(発見できない)
  • 項目が多い階層メニュー
  • 右クリックを別用途で使う画面
構成要素
  • ステージ
  • メニュー
  • 項目(アイコン付き)
  • 区切り線
  • 破壊的項目
  • 結果表示
持っている状態
  • 通常
  • ホバー
  • フォーカス
キーボード

Tab でステージへ、Shift+F10/ContextMenu キーで開くと先頭項目へ。↑↓で巡回、Home/End で端、Enter/Space で実行、Esc で閉じてステージへ戻る。マウスは右クリック、タッチは長押し 500ms

支援技術

role=menu/menuitem、閉じている間は inert+aria-hidden。開いたら先頭項目へフォーカス。破壊的項目は色に加え区切り線の下に置く。選択結果は role=status で通知。reduce で停止

動き

開閉 140ms ease で opacity・scale 0.94→1(origin 左上)。カーソル位置から生えて見せる

デザインの要点

  • メニューは押した座標から生やし、はみ出す分だけ内側へ寄せる。画面端で右クリックしても項目が切れない
  • 開いたら先頭項目へフォーカスを移し、↑↓で巡回・Esc で戻す。マウス専用にすると右クリックできない人が締め出される
  • transform-origin を左上にして 0.94→1 に開く。カーソルの位置から「生えた」ように見え、どこを押したかが残る
  • 「削除する」は区切り線の下に離して朱色にする。隣接させると「名前を変更」の指が削除に届く
実装メモ

プレビューは枠内に収めるため、メニューを position:absolute(ステージ基準)で実装し、座標もステージ内へクランプしています。実際のページで最前面に出すときは position:fixed に変え、body 直下など高い階層へ置き、window の幅・高さでクランプしてください。ブラウザ標準の右クリックメニューは e.preventDefault() で抑止します。キーボードではステージにフォーカスして Shift+F10(または ContextMenu キー)で同じメニューが中央に開きます。

コード(コピーして使えます)

<div class="stage" id="stage" tabindex="0" aria-label="右クリック(キーボードは Shift+F10)でメニューを開く領域">
  <p class="hint" id="hint">ここを<b>右クリック</b><br>(スマホは長押し・キーボードは Shift+F10)</p>

  <div class="ctx-menu" id="ctxMenu" role="menu" aria-hidden="true" inert>
    <button class="ctx-item" role="menuitem">
      <svg width="14" height="14" viewBox="0 0 14 14" fill="none" aria-hidden="true">
        <path d="M2 11.5h10M9 2.5l2.5 2.5-6 6-2.8.5.5-2.8 6-6z" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round"/>
      </svg>
      編集する
    </button>
    <button class="ctx-item" role="menuitem">
      <svg width="14" height="14" viewBox="0 0 14 14" fill="none" aria-hidden="true">
        <rect x="2.5" y="4.5" width="7.5" height="7.5" rx="1.5" stroke="currentColor" stroke-width="1.4"/>
        <path d="M4.5 4.5V3a1.5 1.5 0 011.5-1.5h4A1.5 1.5 0 0111.5 3v4a1.5 1.5 0 01-1.5 1.5" stroke="currentColor" stroke-width="1.4"/>
      </svg>
      複製する
    </button>
    <button class="ctx-item" role="menuitem">
      <svg width="14" height="14" viewBox="0 0 14 14" fill="none" aria-hidden="true">
        <path d="M7 2v7M4 6l3 3 3-3M2.5 11.5h9" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round"/>
      </svg>
      名前を変更
    </button>
    <hr class="ctx-divider" aria-hidden="true"/>
    <button class="ctx-item ctx-item--danger" role="menuitem">
      <svg width="14" height="14" viewBox="0 0 14 14" fill="none" aria-hidden="true">
        <path d="M2.5 3.5h9M5 3.5V2.5a.5.5 0 01.5-.5h3a.5.5 0 01.5.5v1M4.5 3.5l.5 8M9.5 3.5l-.5 8M3.5 3.5l.5 8h6l.5-8" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round"/>
      </svg>
      削除する
    </button>
  </div>

  <p class="ctx-result" id="ctxResult" role="status" aria-live="polite"></p>
</div>

タグ

同じカテゴリ「通知・オーバーレイ」のほかのパーツ

関連パーツ