色適応型、レスポンシブ、アクセシビリティ対応の FAB コンポーネントを構築する方法の基本的な概要。
この記事では、色適応型でレスポンシブな、ユーザー補助に対応した FAB コンポーネントを構築する方法について説明します。デモを試して、ソースを表示しましょう。
動画でご覧になりたい場合は、こちらの YouTube 版をご覧ください。
概要
FAB はパソコンよりもモバイルでよく使用されますが、どちらのシナリオでも一般的です。プライマリ アクションを常に表示し、便利でどこにでも表示されるようにします。このユーザー エクスペリエンス スタイルは、Material 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 は常にビューポート内に表示されるため、便利です。これは、位置 fixed
の優れたユースケースです。このビューポートの位置では、inset-block
と inset-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 ドキュメントでは、フォーカスは上から順に移動します。視覚的な順序を逆転させることで、視覚障碍のあるユーザーとキーボード ユーザーのエクスペリエンスが統一されます。プライマリ アクションのスタイルがミニボタンよりも大きく表示されることで、視覚障碍のあるユーザーにはそれがプライマリ アクションであることが示され、キーボード ユーザーはソースの最初の項目としてそれにフォーカスします。
.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 の一部をデフォルトのアクションよりも小さくすることで、ユーザーが最も頻繁に行うアクションを優先的に表示できます。
ミニ 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;
}
ユーザー補助
FAB のユーザー補助機能で最も重要なのは、ページのキーボード フロー内での配置です。このデモには FAB のみが含まれており、キーボードの順序とフローに関して競合するものがないため、意味のあるキーボード フローを示す機会がありません。フォーカスを奪い合う要素があるシナリオでは、ユーザーがフローのどこで FAB ボタンのフローに入るのかを深く考えることをおすすめします。
ユーザーが FAB コンテナにフォーカスすると、フォーカスした内容をスクリーン リーダーのユーザーに知らせる role="group"
と aria-label="floating action buttons"
が追加されます。戦略的に、デフォルトの FAB を最初に配置して、ユーザーが最初にメインのアクションを見つけられるようにしました。次に、flex-direction: column-reverse;
を使用して、ユーザーが簡単にアクセスできるように、メインボタンを画面下部の指の近くに配置します。デフォルトのボタンは視覚的に目立ち、キーボード ユーザーにとっても最初に表示されるため、ユーザーに非常に似たエクスペリエンスを提供できます。
最後に、スクリーン リーダーのユーザーにはアイコンを非表示にし、ボタンのラベルを提供して、ボタンの用途がわかるようにしてください。これは、<svg>
の aria-hidden="true"
と <button>
の aria-label="Some action"
を使用して、HTML で実行されています。
アニメーション
さまざまな種類のアニメーションを追加して、ユーザー エクスペリエンスを向上させることができます。他の 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-shadow
、background-color
、transform
、outline-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);
}
}
}
まとめ
私がどのように行ったかをご理解いただけたかと思います。では、あなたならどのようにしますか?🙂
アプローチを多様化し、ウェブで構築するさまざまな方法を学びましょう。
デモを作成して、ツイートでリンクを送信してください。下のコミュニティ リミックス セクションに追加します。
コミュニティ リミックス
表示する項目はありません。
リソース
- Github のソースコード