フローティング アクション ボタン(FAB)コンポーネントの作成

色適応性、応答性、アクセシビリティが高い FAB コンポーネントを作成する方法の基本的な概要。

この投稿では、色適応型でレスポンシブでアクセシビリティの高い FAB コンポーネントを構築する方法について、私の考えを共有したいと思います。デモをお試しください。また、ソースを確認してください。

動画をご覧になる場合は、この投稿の YouTube バージョンをご覧ください。

概要

FAB はパソコンよりもモバイルでよく使用されますが、両方のシナリオでよく使用されています。メイン アクションが常に表示されるため、便利であらゆる場所に表示されます。このユーザー エクスペリエンス スタイルはマテリアル UI で有名です。使用方法と配置に関する推奨事項についてはこちらをご覧ください。

要素とスタイル

これらのコントロールの HTML には、コンテナ要素と 1 つ以上のボタンのセットが含まれています。コンテナは FAB をビューポート内に配置し、ボタン間のギャップを管理します。ボタンはミニまたはデフォルトにすることができ、プライマリ アクションとセカンダリ アクションの間でさまざまなものがあります。

FAB コンテナ

この要素は通常の <div> にすることもできますが、目の見えないユーザーにも有利に行い、コンテナの目的と内容を説明するために役立つ属性でタグ付けしましょう。

FAB のマークアップ

まず、CSS がスタイルのためにフックする .fabs クラスから始め、次に role="group"aria-label を追加します。これにより、汎用的なコンテナではなく、名前を付けて目的を持たせることができます。

<div class="fabs" role="group" aria-label="Floating action buttons">
  <!-- buttons will go here -->
</div>

FAB のスタイル

FAB の利便性を高めるために、FAB は常にビューポート内に固定されます。これは位置 fixed の優れたユースケースです。このビューポートの位置では、inset-blockinset-inline を使用して、右から左、左から右など、ユーザーのドキュメント モードを補完するようにしました。カスタム プロパティは、繰り返しを防ぎ、ビューポートの下端と端からの距離を均等にするためにも使用されます。

.fabs {
  --_viewport-margin: 2.5vmin;

  position: fixed;
  z-index: var(--layer-1);

  inset-block: auto var(--_viewport-margin);
  inset-inline: auto var(--_viewport-margin);
}

次に、コンテナの表示 flex を指定し、レイアウト方向を column-reverse に変更します。これにより、子が互いに重なって(列)表示され、その視覚的な順序も逆になります。これにより、最初のフォーカス可能な要素が上部ではなく下部(通常は HTML ドキュメントに従ってフォーカスが移動される場所)になります。表示順序を逆にすると、目の見えるユーザーとキーボード ユーザーのエクスペリエンスが統一されます。メイン アクションのスタイルがミニボタンより大きくなっていることで、目の見えるユーザーにはそれがプライマリ アクションであることが示され、キーボード ユーザーはそれをソースの最初のアイテムとしてフォーカスします。

DevTools がグリッド レイアウトに重ねて表示されている 2 つの FAB ボタン。それらの間のギャップがストライプ パターンで示され、計算された高さと幅も表示されます。

.fabs {
  …

  display: flex;
  flex-direction: column-reverse;
  place-items: center;
  gap: var(--_viewport-margin);
}

中央揃えは place-items で処理されます。gap を使用すると、コンテナに配置された FAB ボタンの間にスペースが追加されます。

FAB ボタン

では、ボタンのスタイルを設定して、ボタンがすべての上に浮かんでいるように見えるようにします。

デフォルトの FAB

スタイルを設定する最初のボタンがデフォルトのボタンです。これがすべての FAB ボタンのベースになります。後で、これらの基本スタイルをできるだけ少なく変更しながら、代替の外観を実現するバリアントを作成します。

FAB マークアップ

<button> 要素が正しい選択です。マウス、タップ、キーボードの優れたユーザー エクスペリエンスが備わっているため、これを土台とすることから始めます。このマークアップで最も重要な点は、aria-hidden="true" を使用してスクリーン リーダーのユーザーに対してアイコンを非表示にし、必要なラベルテキストを <button> マークアップ自体に追加することです。このような場合にラベルを追加する場合は、title を追加して、アイコンが通信しようとしているものに関する情報をマウスユーザーが取得できるようにします。

<button data-icon="plus" class="fab" title="Add new action" aria-label="Add new action">
  <svg aria-hidden="true" width="24" height="24" viewBox="0 0 24 24">...</svg>
</button>

FAB スタイル

まず、このボタンを、シャドウが強調されたパディングされた丸いボタンにしてみましょう。これらは、このボタンの主な定義となる機能です。

.fab {
  --_size: 2rem;

  padding: calc(var(--_size) / 2);
  border-radius: var(--radius-round);
  aspect-ratio: 1;
  box-shadow: var(--shadow-4);
}

次に色を追加しましょう。以前の GUI チャレンジで使用した戦略を使います。 明色と暗色を静的に保持する明確な名前のカスタム プロパティのセットを作成します。次に、ユーザーのシステム環境における色の設定に応じてライト変数またはダーク変数のいずれかに設定するアダプティブなカスタム プロパティを作成します。

.fab {
  …

  /* light button and button hover */
  --_light-bg: var(--pink-6);
  --_light-bg-hover: var(--pink-7);

  /* dark button and button hover */
  --_dark-bg: var(--pink-4);
  --_dark-bg-hover: var(--pink-3);

  /* adaptive variables set to light by default */
  --_bg: var(--_light-bg);

  /* static icon colors set to the adaptive foreground variable */
  --_light-fg: white;
  --_dark-fg: black;
  --_fg: var(--_light-fg);

  /* use the adaptive properties on some styles */
  background: var(--_bg);
  color: var(--_fg);

  &:is(:active, :hover, :focus-visible) {
    --_bg: var(--_light-bg-hover);

    @media (prefers-color-scheme: dark) {
      --_bg: var(--_dark-bg-hover);
    }
  }

  /* if users prefers dark, set adaptive props to dark */
  @media (prefers-color-scheme: dark) {
    --_bg: var(--_dark-bg);
    --_fg: var(--_dark-fg);
  }
}

次に、SVG アイコンがスペースに収まるようにスタイルを追加します。

.fab {
  …

  & > svg {
    inline-size: var(--_size);
    block-size: var(--_size);
    stroke-width: 3px;
  }
}

最後に、操作に関する独自の視覚的なフィードバックを追加したため、ボタンからタップによるハイライト表示を削除します。

.fab {
  -webkit-tap-highlight-color: transparent;
}

ミニ FAB

このセクションの目標は、FAB ボタンのバリエーションを作成することです。一部の FAB をデフォルトのアクションよりも小さくすることで、ユーザーが最も頻繁に実行するアクションを促進できます。

Mini FAB マークアップ

HTML は FAB と同じですが、CSS にバリアントへのフックを提供するために「.mini」クラスを追加します。

<button data-icon="heart" class="fab mini" title="Like action" aria-label="Like action">
  <svg aria-hidden="true" width="24" height="24" viewBox="0 0 24 24">...</svg>
</button>
ミニ FAB スタイル

カスタム プロパティを使用しているため、必要な変更は --_size 変数の調整だけです。

.fab.mini {
  --_size: 1.25rem;
}

2 つのファブボタンが積み重ねられ、上のボタンが下のボタンよりも小さいスクリーンショット。

ユーザー補助

FAB のユーザー補助で覚えておくべき最も重要な点は、ページのキーボード フロー内に配置することです。このデモには FAB のみがあり、キーボードの順序とフローに関して競合することはありません。つまり、有意義なキーボード フローのデモを行う機会はありません。フォーカスを奪うために競合する要素がある場合、ユーザーが FAB ボタンのフローに入る場所は、フローのどこにいるのかをじっくり検討することをおすすめします。

キーボード操作のデモ

ユーザーが FAB コンテナにフォーカスすると、スクリーン リーダーのユーザーにフォーカスした内容を通知する role="group"aria-label="floating action buttons" がすでに追加されています。戦略的に、ユーザーが最初にメイン アクションを見つけられるよう、デフォルトの FAB を最初に配置しました。次に、flex-direction: column-reverse; を使用して、プライマリ ボタンをユーザーの指の近くで、下部に配置して簡単に利用できるようにします。これは利点です。デフォルトのボタンが視覚的に目立ち、キーボード ユーザーにとっても最初に表示されるため、非常によく似たユーザー エクスペリエンスを提供できます。

最後に、スクリーン リーダーのユーザーにはアイコンを非表示にするとともに、ボタンのラベルを付与して、不明なアイコンにならないようにしてください。これは HTML ではすでに <svg>aria-hidden="true"<button>aria-label="Some action" で行われています。

アニメーション

さまざまな種類のアニメーションを追加して、ユーザー エクスペリエンスを高めることができます。他の GUI チャレンジと同様に、カスタム プロパティをいくつかセットアップして、リダクション モーション エクスペリエンスとフルモーション エクスペリエンスの意図を保持します。デフォルトでは、スタイルはユーザーが動きを抑制したいと想定し、prefers-reduced-motion メディアクエリを使用して遷移値をフルモーションに切り替えます。

カスタム プロパティを使用した縮小モーション戦略

CSS --_motion-reduced--_motion-ok--_transition に、3 つのカスタム プロパティが作成されます。最初の 2 つの遷移は、ユーザーの設定に応じて適切な遷移を保持します。最後の変数 --_transition はそれぞれ --_motion-reduced または --_motion-ok に設定されます。

.fab {
  /* box-shadow and background-color can safely be transitioned for reduced motion users */
  --_motion-reduced:
    box-shadow .2s var(--ease-3),
    background-color .3s var(--ease-3);

  /* add transform and outline-offset for users ok with motion */
  --_motion-ok:
    var(--_motion-reduced),
    transform .2s var(--ease-3),
    outline-offset 145ms var(--ease-2);

  /* default the transition styles to reduced motion */
  --_transition: var(--_motion-reduced);

  /* set the transition to our adaptive transition custom property*/
  transition: var(--_transition);

  /* if motion is ok, update the adaptive prop to the respective transition prop */
  @media (prefers-reduced-motion: no-preference) {
    --_transition: var(--_motion-ok);
  }
}

これにより、box-shadowbackground-colortransformoutline-offset の変更を移行して、操作が受け取られたという優れた UI フィードバックをユーザーに提供できます。

次に、translateY を少し調整して、:active の状態を少し調整します。これにより、ボタンの押下効果が向上します。

.fab {
  …

  &:active {
    @media (prefers-reduced-motion: no-preference) {
      transform: translateY(2%);
    }
  }
}

最後に、ボタンの SVG アイコンに変更があれば移行します。

.fab {
  …

  &[data-icon="plus"]:hover > svg {
    transform: rotateZ(.25turn);
  }

  & > svg {
    @media (prefers-reduced-motion: no-preference) {
      will-change: transform;
      transition: transform .5s var(--ease-squish-3);
    }
  }
}

まとめ

私のやり方がわかったところで、どうしたらいいですか? 🙂?

多様なアプローチを活用し、ウェブでアプリをビルドするためのあらゆる方法を学びましょう。

デモを作成してツイートのリンクをお願いします。下のコミュニティ リミックス セクションに追加します。

コミュニティのリミックス

まだ何も表示されません。

リソース