建構懸浮動作按鈕 (FAB) 元件

基本介紹如何建構自動調整顏色、回應式且易於使用的懸浮動作按鈕 (FAB)。

在這篇文章中,我想分享我對於如何建構自動調整顏色、回應式功能,以及無障礙 FAB 元件的想法。歡迎試用示範版查看原始碼

如果你偏好使用影片,也可以觀看這篇 YouTube 文章:

總覽

懸浮動作按鈕 (FAB) 比電腦更常見,但這兩種情況都常見。這些動作會在檢視畫面中保留主要動作,使操作更加便利且完整。這種使用者體驗樣式因 Material UI 而聲名大噪,而有關使用和位置的建議,請參閱這裡

元素和樣式

這些控制項的 HTML 包含一個容器元素和一組一或多個按鈕。容器會將懸浮動作按鈕 (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-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 文件中通常聚焦的位置。反轉視覺順序可使視障使用者和鍵盤使用者的體驗保持一致,因為主要動作的樣式大於迷你按鈕,表示視障使用者表明這是主要動作,鍵盤使用者則會將焦點移至來源中的第一個項目。

兩個懸浮動作按鈕 (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) 相同,但我們新增了「.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>
迷你懸浮動作按鈕 (FAB) 樣式

只要使用自訂屬性,只需調整 --_size 變數即可。

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

兩個懸浮動作按鈕 (FAB) 按鈕堆疊和頂部按鈕小於底部按鈕的螢幕截圖。

無障礙功能

懸浮動作按鈕 (FAB) 無障礙功能最重要的部分,就是放在頁面的鍵盤流程中。這項示範僅包含懸浮動作按鈕 (FAB),因此無法針對鍵盤順序和流程展開競爭,因此無法展示有意義的鍵盤流程。如果有競爭元素需要關注的元素,建議您深入思考使用者應在這個流程中的哪個階段進入懸浮動作按鈕 (FAB)。

鍵盤互動示範

使用者將焦點移至 FAB 容器後,我們已新增 role="group"aria-label="floating action buttons",讓螢幕閱讀器使用者瞭解他們聚焦的內容。根據策略,我會先放置預設懸浮動作按鈕 (FAB),讓使用者先找到主要動作。接著使用 flex-direction: column-reverse;,以視覺方式排列底部的主要按鈕,靠近使用者手指以輕鬆存取。這種做法很棒,因為預設按鈕在視覺上就顯得格外醒目,而鍵盤使用者也會先看到它,提供非常相似的體驗。

最後,別忘了向螢幕閱讀器使用者隱藏圖示,並確保為按鈕加上按鈕標籤,以免讓使用者感到困惑。在 HTML 中,<svg><button> 上的 aria-label="Some action" 已有 aria-hidden="true" 一樣。

動畫

您可以新增多種類型的動畫,改善使用者體驗。如同其他 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-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);
    }
  }
}

結語

現在既然你已經知道我怎麼做,你會怎麼做‽ 🙂?

讓我們帶您更多元的方法,並瞭解運用網路打造網站的所有方式。

請建立示範並透過 Twitter 推文連結,我就能將這項工具新增至下方的「社群重混」部分!

社群重混作品

這裡還沒有內容。

資源