フローティングアクションボタン

右下に固定した丸ボタンを押すと、関連アクションが扇状に開くフローティングメニュー(FAB)。問い合わせ・電話・トップへ等をまとめられます。モバイルサイトやアプリ風UIで重宝します。

#sticky#fab#menu#mobile

ライブデモ

使用例(お題: SaaS FlowDesk)

この技法を「SaaS FlowDesk」というテーマのダミーサイトで実際に使った例です。

HTML
<!-- FlowDesk:アプリ風UIのフローティングアクション -->
<div class="sfb-frame">
  <div class="sfb-stage">
    <h1>クイックアクション</h1>
    <p>右下のボタンから、よく使う操作にすぐアクセス。<br>(自動でも開閉を実演します)</p>
  </div>

  <div class="sfb" id="sfb">
    <a class="sfb-action" style="--i:3" href="#" onclick="return false" aria-label="新規タスク"><span>+</span><i class="sfb-tip">新規タスク</i></a>
    <a class="sfb-action" style="--i:2" href="#" onclick="return false" aria-label="招待"><span>👤</span><i class="sfb-tip">メンバー招待</i></a>
    <a class="sfb-action" style="--i:1" href="#" onclick="return false" aria-label="ヘルプ"><span>?</span><i class="sfb-tip">ヘルプ</i></a>
    <button class="sfb-main" id="sfbMain" type="button" aria-label="メニュー" aria-expanded="false">
      <span class="sfb-plus">+</span>
    </button>
  </div>
</div>
CSS
/* FlowDesk(SaaS):フローティングアクションボタンの再スキン */
* { box-sizing: border-box; }
body { margin: 0; font-family: "Segoe UI", system-ui, -apple-system, sans-serif; }

.sfb-frame { position: relative; width: 100%; height: 380px; overflow: hidden; background: linear-gradient(135deg, #eaf0ff, #f7f8fc); }

.sfb-stage { display: grid; place-content: center; height: 100%; text-align: center; color: #2a3050; padding: 0 24px; }
.sfb-stage h1 { margin: 0; font-size: 26px; font-weight: 800; }
.sfb-stage p { margin: 12px 0 0; font-size: 13px; line-height: 1.8; color: #6a7090; }

.sfb { position: absolute; right: 20px; bottom: 20px; z-index: 10; width: 56px; height: 56px; }
.sfb-main { position: absolute; right: 0; bottom: 0; z-index: 2; width: 56px; height: 56px; border-radius: 50%; cursor: pointer; border: none; background: linear-gradient(135deg, #4f6bff, #6d28d9); color: #fff; box-shadow: 0 12px 26px rgba(79,107,255,.4); display: grid; place-items: center; transition: transform .3s ease; }
.sfb-plus { font-size: 26px; line-height: 1; transition: transform .3s ease; }
.sfb.is-open .sfb-plus { transform: rotate(135deg); }
.sfb-main:hover { transform: scale(1.06); }

.sfb-action { position: absolute; right: 6px; bottom: 6px; z-index: 1; width: 44px; height: 44px; border-radius: 50%; display: grid; place-items: center; text-decoration: none; background: #fff; color: #4f46e5; font-size: 17px; box-shadow: 0 8px 18px rgba(40,55,160,.16); opacity: 0; transform: translateY(0) scale(.6); pointer-events: none; transition: transform .3s cubic-bezier(.2,.8,.2,1), opacity .25s ease; }
.sfb.is-open .sfb-action { opacity: 1; pointer-events: auto; transform: translateY(calc(var(--i) * -58px)) scale(1); transition-delay: calc(var(--i) * 40ms); }
.sfb-tip { position: absolute; right: 54px; top: 50%; transform: translateY(-50%); font-style: normal; font-size: 12px; font-weight: 700; white-space: nowrap; background: #1f2433; color: #fff; padding: 5px 10px; border-radius: 7px; opacity: 0; transition: opacity .2s ease; }
.sfb-action:hover .sfb-tip { opacity: 1; }

@media (prefers-reduced-motion: reduce) { .sfb-main, .sfb-plus, .sfb-action { transition: none; } }
JavaScript
// (デモと同じフックを流用)FABの開閉+自動実演
(() => {
  const fab = document.getElementById('sfb');
  const main = document.getElementById('sfbMain');
  if (!fab || !main) return;
  const set = (open) => { fab.classList.toggle('is-open', open); main.setAttribute('aria-expanded', open ? 'true' : 'false'); };
  let auto = !matchMedia('(prefers-reduced-motion: reduce)').matches;
  main.addEventListener('click', () => { auto = false; set(!fab.classList.contains('is-open')); });
  if (auto) {
    let open = false;
    const tick = () => { if (!auto) return; open = !open; set(open); setTimeout(tick, open ? 2400 : 1600); };
    setTimeout(tick, 1000);
  }
})();

実装ガイド

使いどころ

モバイルサイトやアプリ風UIで、主要アクションへ素早く導きたいときに。右下の丸ボタンを押すと、関連アクション(新規・招待・ヘルプ等)が扇状に開きます。

実装時の注意点

アクション群は --i を使った translateY と transition-delay で順に立ち上がり、メインボタンの+は rotate(135deg) で×へ。is-open クラスの付け外しだけで全体が連動します。JS はクリック開閉とプレビュー用の自動開閉です。

対応ブラウザ

transform・transition・CSS 変数演算(calc)は全モダンブラウザで対応します。

よくある失敗

開いた状態で外側タップやEscで閉じる導線を用意すること。アクション数が多いと縦に伸びて画面外へ出るため3〜4個に絞るか弧状配置に。最前面に置くと他UIを隠すので z-index と位置に注意します。

応用例

弧状・横展開のレイアウト、ラベル常時表示、スクロールで隠す、メインボタンのアイコンを状況で変えるなどの拡張ができます。

コード

HTML
<!-- 扇状に開くフローティングアクションボタン(FAB) -->
<div class="sfb-frame">
  <div class="sfb-stage">
    <h1>フローティングアクション</h1>
    <p>右下のボタンを押すと、関連アクションが開きます。<br>(自動でも開閉を実演します)</p>
  </div>

  <div class="sfb" id="sfb">
    <a class="sfb-action" style="--i:3" href="#" onclick="return false" aria-label="トップへ"><span>↑</span><i class="sfb-tip">トップへ</i></a>
    <a class="sfb-action" style="--i:2" href="#" onclick="return false" aria-label="電話"><span>✆</span><i class="sfb-tip">電話する</i></a>
    <a class="sfb-action" style="--i:1" href="#" onclick="return false" aria-label="メール"><span>✉</span><i class="sfb-tip">問い合わせ</i></a>
    <button class="sfb-main" id="sfbMain" type="button" aria-label="メニュー" aria-expanded="false">
      <span class="sfb-plus">+</span>
    </button>
  </div>
</div>
CSS
* { box-sizing: border-box; }
body { margin: 0; font-family: "Segoe UI", system-ui, -apple-system, sans-serif; }

.sfb-frame { position: relative; width: 100%; height: 380px; overflow: hidden; background: linear-gradient(135deg, #eef2ff, #f8f7fb); }

.sfb-stage { display: grid; place-content: center; height: 100%; text-align: center; color: #2b2d38; padding: 0 24px; }
.sfb-stage h1 { margin: 0; font-size: 26px; font-weight: 800; }
.sfb-stage p { margin: 12px 0 0; font-size: 13px; line-height: 1.8; color: #6b7180; }

.sfb { position: absolute; right: 20px; bottom: 20px; z-index: 10; width: 56px; height: 56px; }

.sfb-main {
  position: absolute; right: 0; bottom: 0; z-index: 2;
  width: 56px; height: 56px; border-radius: 50%; cursor: pointer; border: none;
  background: linear-gradient(135deg, #6366f1, #8b5cf6); color: #fff;
  box-shadow: 0 12px 26px rgba(99,102,241,.4);
  display: grid; place-items: center;
  transition: transform .3s ease;
}
.sfb-plus { font-size: 26px; line-height: 1; transition: transform .3s ease; }
.sfb.is-open .sfb-plus { transform: rotate(135deg); }
.sfb-main:hover { transform: scale(1.06); }

.sfb-action {
  position: absolute; right: 6px; bottom: 6px; z-index: 1;
  width: 44px; height: 44px; border-radius: 50%;
  display: grid; place-items: center; text-decoration: none;
  background: #fff; color: #4f46e5; font-size: 18px;
  box-shadow: 0 8px 18px rgba(20,24,40,.16);
  opacity: 0; transform: translateY(0) scale(.6); pointer-events: none;
  transition: transform .3s cubic-bezier(.2,.8,.2,1), opacity .25s ease;
}
.sfb.is-open .sfb-action {
  opacity: 1; pointer-events: auto;
  transform: translateY(calc(var(--i) * -58px)) scale(1);
  transition-delay: calc(var(--i) * 40ms);
}

.sfb-tip {
  position: absolute; right: 54px; top: 50%; transform: translateY(-50%);
  font-style: normal; font-size: 12px; font-weight: 700; white-space: nowrap;
  background: #1f2433; color: #fff; padding: 5px 10px; border-radius: 7px;
  opacity: 0; transition: opacity .2s ease;
}
.sfb-action:hover .sfb-tip { opacity: 1; }

@media (prefers-reduced-motion: reduce) {
  .sfb-main, .sfb-plus, .sfb-action { transition: none; }
}
JavaScript
// FABの開閉。プレビューでは自動でも開閉を実演
(() => {
  const fab = document.getElementById('sfb');
  const main = document.getElementById('sfbMain');
  if (!fab || !main) return;

  const set = (open) => {
    fab.classList.toggle('is-open', open);
    main.setAttribute('aria-expanded', open ? 'true' : 'false');
  };

  let auto = !matchMedia('(prefers-reduced-motion: reduce)').matches;
  main.addEventListener('click', () => { auto = false; set(!fab.classList.contains('is-open')); });

  if (auto) {
    let open = false;
    const tick = () => {
      if (!auto) return;
      open = !open; set(open);
      setTimeout(tick, open ? 2400 : 1600);
    };
    setTimeout(tick, 1000);
  }
})();

🤖 AIエージェント用プロンプト

このままコピーしてAIに貼り付け「追加する場所」だけ書き換えればOK
あなたは熟練のフロントエンドエンジニアです。私のWebサイトに「フローティングアクションボタン」の効果を追加してください。

# 追加してほしい効果
フローティングアクションボタン(追従ウィジェット)
右下に固定した丸ボタンを押すと、関連アクションが扇状に開くフローティングメニュー(FAB)。問い合わせ・電話・トップへ等をまとめられます。モバイルサイトやアプリ風UIで重宝します。

# 追加する場所
👉【ここに対象箇所を記入:例「トップのヒーローセクション」「お問い合わせボタン」「記事カードの一覧」など】

# 参考実装(この見た目・挙動を再現してください)
【HTML】
<!-- 扇状に開くフローティングアクションボタン(FAB) -->
<div class="sfb-frame">
  <div class="sfb-stage">
    <h1>フローティングアクション</h1>
    <p>右下のボタンを押すと、関連アクションが開きます。<br>(自動でも開閉を実演します)</p>
  </div>

  <div class="sfb" id="sfb">
    <a class="sfb-action" style="--i:3" href="#" onclick="return false" aria-label="トップへ"><span>↑</span><i class="sfb-tip">トップへ</i></a>
    <a class="sfb-action" style="--i:2" href="#" onclick="return false" aria-label="電話"><span>✆</span><i class="sfb-tip">電話する</i></a>
    <a class="sfb-action" style="--i:1" href="#" onclick="return false" aria-label="メール"><span>✉</span><i class="sfb-tip">問い合わせ</i></a>
    <button class="sfb-main" id="sfbMain" type="button" aria-label="メニュー" aria-expanded="false">
      <span class="sfb-plus">+</span>
    </button>
  </div>
</div>

【CSS】
* { box-sizing: border-box; }
body { margin: 0; font-family: "Segoe UI", system-ui, -apple-system, sans-serif; }

.sfb-frame { position: relative; width: 100%; height: 380px; overflow: hidden; background: linear-gradient(135deg, #eef2ff, #f8f7fb); }

.sfb-stage { display: grid; place-content: center; height: 100%; text-align: center; color: #2b2d38; padding: 0 24px; }
.sfb-stage h1 { margin: 0; font-size: 26px; font-weight: 800; }
.sfb-stage p { margin: 12px 0 0; font-size: 13px; line-height: 1.8; color: #6b7180; }

.sfb { position: absolute; right: 20px; bottom: 20px; z-index: 10; width: 56px; height: 56px; }

.sfb-main {
  position: absolute; right: 0; bottom: 0; z-index: 2;
  width: 56px; height: 56px; border-radius: 50%; cursor: pointer; border: none;
  background: linear-gradient(135deg, #6366f1, #8b5cf6); color: #fff;
  box-shadow: 0 12px 26px rgba(99,102,241,.4);
  display: grid; place-items: center;
  transition: transform .3s ease;
}
.sfb-plus { font-size: 26px; line-height: 1; transition: transform .3s ease; }
.sfb.is-open .sfb-plus { transform: rotate(135deg); }
.sfb-main:hover { transform: scale(1.06); }

.sfb-action {
  position: absolute; right: 6px; bottom: 6px; z-index: 1;
  width: 44px; height: 44px; border-radius: 50%;
  display: grid; place-items: center; text-decoration: none;
  background: #fff; color: #4f46e5; font-size: 18px;
  box-shadow: 0 8px 18px rgba(20,24,40,.16);
  opacity: 0; transform: translateY(0) scale(.6); pointer-events: none;
  transition: transform .3s cubic-bezier(.2,.8,.2,1), opacity .25s ease;
}
.sfb.is-open .sfb-action {
  opacity: 1; pointer-events: auto;
  transform: translateY(calc(var(--i) * -58px)) scale(1);
  transition-delay: calc(var(--i) * 40ms);
}

.sfb-tip {
  position: absolute; right: 54px; top: 50%; transform: translateY(-50%);
  font-style: normal; font-size: 12px; font-weight: 700; white-space: nowrap;
  background: #1f2433; color: #fff; padding: 5px 10px; border-radius: 7px;
  opacity: 0; transition: opacity .2s ease;
}
.sfb-action:hover .sfb-tip { opacity: 1; }

@media (prefers-reduced-motion: reduce) {
  .sfb-main, .sfb-plus, .sfb-action { transition: none; }
}

【JavaScript】
// FABの開閉。プレビューでは自動でも開閉を実演
(() => {
  const fab = document.getElementById('sfb');
  const main = document.getElementById('sfbMain');
  if (!fab || !main) return;

  const set = (open) => {
    fab.classList.toggle('is-open', open);
    main.setAttribute('aria-expanded', open ? 'true' : 'false');
  };

  let auto = !matchMedia('(prefers-reduced-motion: reduce)').matches;
  main.addEventListener('click', () => { auto = false; set(!fab.classList.contains('is-open')); });

  if (auto) {
    let open = false;
    const tick = () => {
      if (!auto) return;
      open = !open; set(open);
      setTimeout(tick, open ? 2400 : 1600);
    };
    setTimeout(tick, 1000);
  }
})();

# 外部ライブラリ
なし(追加ライブラリ不要)

# 守ってほしいこと
- 既存のHTML構造・レイアウト・デザインを壊さないこと。必要に応じてクラス名・色・サイズを私のサイトに合わせて調整してよい。
- クラス名やidが既存と衝突しないよう、必要なら接頭辞で名前空間を分けること。
- レスポンシブ対応と prefers-reduced-motion への配慮を入れること。
- 私のサイトのフレームワーク(React / Vue / 素のHTML など)に合わせて実装すること。不明な場合は素のHTML/CSS/JSで提示し、組み込み手順も説明すること。
- 変更後の確認手順も簡潔に教えてください。