Membuat komponen tombol tindakan mengambang (FAB)

Ringkasan dasar tentang cara membuat komponen FAB yang responsif, dapat diakses, dan dapat menyesuaikan warna.

Dalam postingan ini, saya ingin membagikan pemikiran saya tentang cara membuat komponen FAB yang adaptif terhadap warna, responsif, dan mudah diakses. Coba demo dan lihat sumbernya.

Jika Anda lebih suka menonton video, berikut versi YouTube dari postingan ini:

Ringkasan

FAB lebih umum digunakan di perangkat seluler daripada desktop, tetapi FAB banyak digunakan dalam kedua skenario tersebut. Tindakan ini menjaga tindakan utama tetap terlihat, sehingga nyaman dan selalu ada. Gaya pengalaman pengguna ini dipopulerkan oleh Material UI dan saran mereka untuk penggunaan dan penempatan dapat ditemukan di sini.

Elemen dan gaya

HTML untuk kontrol ini melibatkan elemen penampung dan serangkaian satu atau beberapa tombol. Penampung memosisikan FAB dalam area tampilan dan mengelola jarak antar-tombol. Tombol dapat berukuran mini atau default, sehingga memberikan variasi yang bagus antara tindakan utama dan sekunder.

Penampung FAB

Elemen ini dapat berupa <div> biasa, tetapi mari kita bantu pengguna yang tidak dapat melihat dengan menandainya menggunakan beberapa atribut yang berguna untuk menjelaskan tujuan dan isi penampung ini.

Markup FAB

Mulai dengan class .fabs untuk CSS yang akan digunakan untuk gaya, lalu tambahkan role="group" dan aria-label sehingga bukan hanya penampung generik, tetapi diberi nama dan memiliki tujuan.

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

Gaya FAB

Agar FAB nyaman digunakan, FAB akan selalu berada di dalam area tampilan. Ini adalah kasus penggunaan yang bagus untuk posisi fixed. Dalam posisi area tampilan ini, saya memilih untuk menggunakan inset-block dan inset-inline sehingga posisi akan melengkapi mode dokumen pengguna, seperti kanan-ke-kiri atau kiri-ke-kanan. Properti kustom juga digunakan untuk mencegah pengulangan dan memastikan jarak yang sama dari tepi bawah dan samping area tampilan:

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

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

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

Selanjutnya, saya memberikan tampilan penampung flex dan mengubah arah tata letaknya menjadi column-reverse. Tindakan ini menumpuk turunan di atas satu sama lain (kolom) dan juga membalikkan urutan visualnya. Hal ini akan membuat elemen pertama yang dapat difokuskan menjadi elemen bawah, bukan elemen atas, yang biasanya menjadi tempat fokus berdasarkan dokumen HTML. Membalikkan urutan visual menyatukan pengalaman bagi pengguna yang dapat melihat dan pengguna keyboard, karena gaya tindakan utama yang lebih besar daripada tombol mini menunjukkan kepada pengguna yang dapat melihat bahwa itu adalah tindakan utama, dan pengguna keyboard akan memfokuskannya sebagai item pertama dalam sumber.

Dua tombol fab ditampilkan dengan DevTools yang melapisi tata letak petaknya. Menampilkan celah di antara keduanya dengan pola bergaris dan juga menampilkan tinggi dan lebar yang dihitung.

.fabs {
  

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

Penyejajaran ditangani dengan place-items, dan gap menambahkan ruang di antara tombol FAB yang ditempatkan di penampung.

Tombol FAB

Saatnya menata gaya beberapa tombol agar terlihat mengambang di atas semuanya.

FAB Default

Tombol pertama yang akan diberi gaya adalah tombol default. Tombol ini akan berfungsi sebagai dasar untuk semua tombol FAB. Nanti kita akan membuat varian yang mencapai tampilan alternatif sambil memodifikasi gaya dasar ini sesedikit mungkin.

Markup FAB

Elemen <button> adalah pilihan yang tepat. Kita akan memulai dengan ini sebagai dasar karena dilengkapi dengan pengalaman pengguna mouse, sentuhan, dan keyboard yang luar biasa. Aspek markup yang paling penting ini adalah menyembunyikan ikon dari pengguna pembaca layar dengan aria-hidden="true" dan menambahkan teks label yang diperlukan ke markup <button> itu sendiri. Saat menambahkan label dalam kasus ini, saya juga suka menambahkan title sehingga pengguna mouse dapat memperoleh informasi tentang maksud ikon tersebut.

<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>

Gaya FAB

Pertama, ubah tombol menjadi tombol bulat dengan padding dan bayangan yang kuat, karena ini adalah fitur penentu pertama tombol:

.fab {
  --_size: 2rem;

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

Selanjutnya, mari kita tambahkan warna. Kita akan menggunakan strategi yang telah kita gunakan dalam Tantangan GUI sebelumnya. Buat serangkaian properti kustom yang diberi nama dengan jelas yang secara statis menyimpan warna terang dan gelap, lalu properti kustom adaptif yang akan ditetapkan ke variabel terang atau gelap, bergantung pada preferensi sistem pengguna untuk warna:

.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);
  }
}

Selanjutnya, tambahkan beberapa gaya untuk membantu ikon SVG sesuai dengan ruang.

.fab {
  

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

Terakhir, hapus tanda ketuk dari tombol karena kita telah menambahkan respons visual sendiri untuk interaksi:

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

FAB Mini

Tujuan bagian ini adalah membuat varian untuk tombol FAB. Dengan membuat beberapa FAB lebih kecil daripada tindakan default, kita dapat mempromosikan tindakan yang paling sering dilakukan pengguna.

Markup FAB mini

HTML-nya sama dengan FAB, tetapi kita menambahkan class ".mini" untuk memberi CSS hook ke dalam varian.

<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>
Gaya FAB mini

Berkat penggunaan properti kustom, satu-satunya perubahan yang diperlukan adalah penyesuaian pada variabel --_size.

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

Screenshot dua tombol FAB yang disusun dan tombol atas lebih kecil daripada tombol di bawah.

Aksesibilitas

Bagian terpenting yang perlu diingat untuk aksesibilitas dengan FAB adalah penempatan dalam alur keyboard halaman. Demo ini hanya memiliki FAB, tidak ada yang dapat bersaing dalam hal urutan dan alur keyboard, yang berarti demo ini tidak memiliki kesempatan untuk mendemonstrasikan alur keyboard yang bermakna. Dalam skenario ketika ada elemen yang bersaing untuk mendapatkan fokus, sebaiknya pikirkan secara matang di mana dalam alur tersebut pengguna akan menemukan dirinya memasuki alur tombol FAB.

Demonstrasi interaksi keyboard

Setelah pengguna berfokus pada penampung FAB, kita telah menambahkan role="group" dan aria-label="floating action buttons" yang memberi tahu pengguna pembaca layar tentang konten yang telah mereka fokuskan. Secara strategis, saya telah menempatkan FAB default terlebih dahulu, sehingga pengguna menemukan tindakan utama terlebih dahulu. Kemudian, saya menggunakan flex-direction: column-reverse; untuk mengurutkan tombol utama secara visual di bagian bawah, dekat dengan jari pengguna agar mudah diakses. Ini adalah kemenangan yang bagus karena tombol default terlihat jelas dan juga yang pertama bagi pengguna keyboard, sehingga memberikan pengalaman yang sangat serupa.

Terakhir, jangan lupa untuk menyembunyikan ikon Anda dari pengguna pembaca layar dan pastikan Anda memberi mereka label untuk tombol tersebut agar tidak menjadi misteri. Hal ini telah dilakukan di HTML dengan aria-hidden="true" di <svg> dan aria-label="Some action" di <button>.

Animasi

Berbagai jenis animasi dapat ditambahkan untuk meningkatkan pengalaman pengguna. Seperti dalam Tantangan GUI lainnya, kita akan menyiapkan beberapa properti kustom untuk menyimpan maksud pengalaman gerakan yang dikurangi dan pengalaman gerakan penuh. Secara default, gaya akan mengasumsikan pengguna menginginkan gerakan yang dikurangi, lalu menggunakan kueri media prefers-reduced-motion untuk menukar nilai transisi ke gerakan penuh.

Strategi pengurangan gerakan dengan properti kustom

Tiga properti kustom dibuat di CSS berikut: --_motion-reduced, --_motion-ok, dan --_transition. Dua yang pertama menyimpan transisi yang sesuai mengingat preferensi pengguna, dan variabel terakhir --_transition akan ditetapkan ke --_motion-reduced atau --_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);
  }
}

Dengan adanya hal di atas, perubahan pada box-shadow, background-color, transform, dan outline-offset dapat ditransisikan, sehingga memberikan masukan UI yang bagus kepada pengguna bahwa interaksi mereka telah diterima.

Selanjutnya, tambahkan sedikit sentuhan pada status :active dengan menyesuaikan translateYsedikit, sehingga tombol memiliki efek ditekan yang bagus:

.fab {
  

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

Terakhir, lakukan transisi pada setiap perubahan pada ikon SVG di tombol:

.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);
    }
  }
}

Kesimpulan

Sekarang setelah Anda tahu cara saya melakukannya, bagaimana Anda‽ 🙂

Mari kita diversifikasi pendekatan kita dan pelajari semua cara untuk membangun di web.

Buat demo, tweet linknya kepada saya, dan saya akan menambahkannya ke bagian remix komunitas di bawah.

Remix komunitas

Belum ada apa-apa di sini.

Resource