概略說明如何建構可自動調整顏色、反應且無障礙的懸浮動作按鈕 (FAB) 元件。
在這篇文章中,我想分享如何建構可自適應顏色、回應式且無障礙的 FAB 元件。試用示範並查看來源!
如果你偏好觀看影片,請參閱這篇文章的 YouTube 版本:
總覽
FAB 在行動裝置上更常見,而非電腦。讓主要動作一覽無遺,方便使用者隨時隨地使用。這種使用者體驗風格是由 Material UI 所推廣,您可以在此找到他們提供的使用和放置建議。
元素和樣式
這些控制項的 HTML 包含容器元素和一組或多個按鈕。容器會將 FAB 置於可視區域內,並管理按鈕之間的間距。按鈕可以是迷你或預設按鈕,讓主要和次要動作之間有更多變化。
懸浮動作按鈕容器
這個元素可以是一般 <div>
,但我們還是為視障使用者著想,為這個容器加上一些實用的屬性標記,說明容器的用途和內容。
懸浮動作按鈕 (FAB) 標記
請先使用 .fabs
類別,讓 CSS 連結至樣式,然後新增 role="group"
和 aria-label
,讓其不只是一般容器,而是具備名稱和用途。
<div class="fabs" role="group" aria-label="Floating action buttons">
<!-- buttons will go here -->
</div>
懸浮動作按鈕樣式
為了讓懸浮動作按鈕 (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 相同,但我們會加入「.mini」類別,讓 CSS 鉤住變化版本。
<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>
迷你懸浮動作按鈕樣式
由於使用了自訂屬性,您只需要調整 --_size
變數。
.fab.mini {
--_size: 1.25rem;
}
無障礙設定
在使用 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
。前兩個變數會根據使用者的偏好設定適當的轉場效果,而最後一個變數 --_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 上的原始碼