Xây dựng thành phần nút hành động nổi (FAB)

Thông tin tổng quan cơ bản về cách tạo các thành phần FAB thích ứng với màu sắc, có khả năng thích ứng và dễ tiếp cận.

Trong bài đăng này, tôi muốn chia sẻ suy nghĩ của mình về cách tạo các thành phần FAB có khả năng thích ứng với màu sắc, có tính phản hồi và hỗ trợ tiếp cận. Hãy dùng thử bản minh hoạxem nguồn!

Nếu bạn thích xem video, thì đây là phiên bản video của bài đăng này trên YouTube:

Tổng quan

FAB phổ biến hơn trên thiết bị di động so với máy tính, nhưng chúng phổ biến trong cả hai trường hợp. Các nút này luôn hiển thị các thao tác chính, giúp người dùng dễ dàng thực hiện thao tác ở mọi nơi. Phong cách trải nghiệm người dùng này nổi tiếng nhờ Material UI và bạn có thể tìm thấy các đề xuất của họ về cách sử dụng và vị trí tại đây.

Phần tử và kiểu

HTML cho các chế độ kiểm soát này bao gồm một phần tử vùng chứa và một nhóm gồm một hoặc nhiều nút. Vùng chứa này đặt các FAB trong khung nhìn và quản lý khoảng trống giữa các nút. Các nút có thể là nút nhỏ hoặc nút mặc định, mang đến sự đa dạng giữa các hành động chính và phụ.

Vùng chứa FAB

Phần tử này có thể là một <div> thông thường, nhưng hãy giúp những người dùng khiếm thị bằng cách gắn thẻ phần tử này với một số thuộc tính hữu ích để giải thích mục đích và nội dung của vùng chứa này.

Ngôn ngữ đánh dấu FAB

Bắt đầu bằng một lớp .fabs cho CSS để liên kết vào kiểu, sau đó thêm role="group"aria-label để lớp này không chỉ là một vùng chứa chung mà còn có tên và mục đích.

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

Kiểu FAB

Để thuận tiện, các FAB luôn nằm trong khung nhìn. Đây là một trường hợp sử dụng tuyệt vời cho vị trí fixed. Trong vị trí khung hiển thị này, tôi chọn sử dụng inset-blockinset-inline để vị trí này sẽ bổ sung cho chế độ tài liệu của người dùng, chẳng hạn như từ phải sang trái hoặc từ trái sang phải. Các thuộc tính tuỳ chỉnh cũng được dùng để ngăn chặn sự lặp lại và đảm bảo khoảng cách bằng nhau từ các cạnh dưới cùng và bên của khung hiển thị:

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

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

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

Tiếp theo, tôi sẽ cung cấp màn hình vùng chứa flex và thay đổi hướng bố cục của màn hình này thành column-reverse. Thao tác này xếp các phần tử con chồng lên nhau (cột) và cũng đảo ngược thứ tự hiển thị của chúng. Điều này có tác dụng làm cho phần tử có thể lấy tiêu điểm đầu tiên trở thành phần tử dưới cùng thay vì phần tử trên cùng. Đây là vị trí mà tiêu điểm thường chuyển đến theo tài liệu HTML. Việc đảo ngược thứ tự hiển thị sẽ hợp nhất trải nghiệm cho người dùng nhìn thấy và người dùng bàn phím, vì kiểu dáng của thao tác chính lớn hơn các nút nhỏ cho người dùng nhìn thấy biết rằng đó là thao tác chính và người dùng bàn phím sẽ tập trung vào thao tác đó với tư cách là mục đầu tiên trong nguồn.

Hai nút thao tác nổi xuất hiện với Công cụ cho nhà phát triển phủ lên bố cục dạng lưới của chúng. Hiện khoảng trống giữa các thành phần này bằng một mẫu sọc, đồng thời cho biết chiều cao và chiều rộng được tính toán của chúng.

.fabs {
  

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

Việc căn giữa được xử lý bằng place-itemsgap sẽ thêm khoảng cách giữa mọi nút FAB được đặt trong vùng chứa.

Nút FAB

Đã đến lúc tạo kiểu cho một số nút để trông như thể chúng đang nổi phía trên mọi thứ.

FAB mặc định

Nút đầu tiên cần tạo kiểu là nút mặc định. Đây sẽ là cơ sở cho tất cả các nút FAB. Sau đó, chúng ta sẽ tạo một biến thể có giao diện thay thế trong khi sửa đổi ít nhất có thể các kiểu cơ bản này.

Ngôn ngữ đánh dấu FAB

Phần tử <button> là lựa chọn phù hợp. Chúng tôi sẽ bắt đầu với lựa chọn này làm cơ sở vì lựa chọn này mang lại trải nghiệm tuyệt vời cho người dùng khi dùng chuột, thao tác chạm và bàn phím. Khía cạnh quan trọng nhất của mã đánh dấu này là ẩn biểu tượng đối với người dùng trình đọc màn hình bằng aria-hidden="true" và thêm văn bản nhãn cần thiết vào chính mã đánh dấu <button>. Khi thêm nhãn trong những trường hợp này, tôi cũng muốn thêm một title để người dùng chuột có thể biết thông tin về ý nghĩa của biểu tượng.

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

Kiểu FAB

Trước tiên, hãy biến nút này thành một nút tròn có phần đệm và bóng đổ rõ nét, vì đây là những đặc điểm xác định đầu tiên của nút:

.fab {
  --_size: 2rem;

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

Tiếp theo, hãy thêm màu. Chúng ta sẽ sử dụng một chiến lược mà chúng ta đã từng sử dụng trong các Thử thách về giao diện người dùng đồ hoạ. Tạo một nhóm thuộc tính tuỳ chỉnh được đặt tên rõ ràng để giữ cố định màu sáng và màu tối, sau đó tạo một thuộc tính tuỳ chỉnh thích ứng sẽ được đặt thành biến sáng hoặc biến tối tuỳ thuộc vào lựa chọn ưu tiên của người dùng đối với màu sắc trên hệ thống:

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

Tiếp theo, hãy thêm một số kiểu để giúp các biểu tượng SVG vừa với không gian.

.fab {
  

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

Cuối cùng, hãy xoá điểm nổi bật khi nhấn khỏi nút vì chúng ta đã thêm phản hồi trực quan của riêng mình cho hoạt động tương tác:

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

Nút hành động nổi cỡ nhỏ

Mục tiêu của phần này là tạo một biến thể cho nút FAB. Bằng cách làm cho một số FAB nhỏ hơn hành động mặc định, chúng ta có thể quảng bá hành động mà người dùng thực hiện thường xuyên nhất.

Ngôn ngữ đánh dấu FAB thu nhỏ

HTML này giống như FAB nhưng chúng ta sẽ thêm lớp ".mini" để cung cấp cho CSS một hook vào biến thể.

<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>
Kiểu FAB thu nhỏ

Nhờ việc sử dụng các thuộc tính tuỳ chỉnh, thay đổi duy nhất cần thiết là điều chỉnh biến --_size.

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

Ảnh chụp màn hình cho thấy 2 nút thao tác nổi được xếp chồng lên nhau và nút trên cùng nhỏ hơn nút dưới cùng.

Hỗ trợ tiếp cận

Phần quan trọng nhất cần nhớ để hỗ trợ tiếp cận bằng FAB là vị trí trong quy trình bàn phím của trang. Bản minh hoạ này chỉ có các FAB, không có gì cạnh tranh về thứ tự và luồng bàn phím, tức là bản minh hoạ này không có cơ hội minh hoạ một luồng bàn phím có ý nghĩa. Trong trường hợp có các phần tử cạnh tranh để lấy tiêu điểm, tôi đề xuất bạn suy nghĩ kỹ về vị trí trong luồng đó mà người dùng sẽ thấy mình đang tham gia vào luồng nút FAB.

Minh hoạ tương tác bằng bàn phím

Sau khi người dùng tập trung vào vùng chứa FAB, chúng tôi đã thêm role="group"aria-label="floating action buttons" để thông báo cho người dùng trình đọc màn hình về nội dung mà họ đã tập trung. Về mặt chiến lược, tôi đã đặt FAB mặc định lên trước để người dùng tìm thấy hành động chính trước tiên. Sau đó, tôi sử dụng flex-direction: column-reverse; để sắp xếp trực quan nút chính ở dưới cùng, gần ngón tay của người dùng để dễ dàng truy cập. Đây là một điểm cộng vì nút mặc định nổi bật về mặt hình ảnh và cũng là nút đầu tiên đối với người dùng bàn phím, mang đến cho họ trải nghiệm rất tương đồng.

Cuối cùng, đừng quên ẩn các biểu tượng của bạn khỏi người dùng trình đọc màn hình và đảm bảo bạn cung cấp cho họ nhãn cho nút để họ không bị nhầm lẫn. Việc này đã được thực hiện trong HTML bằng aria-hidden="true" trên <svg>aria-label="Some action" trên <button>.

Hoạt ảnh

Bạn có thể thêm nhiều loại ảnh động để nâng cao trải nghiệm người dùng. Giống như trong các Thử thách khác về GUI, chúng ta sẽ thiết lập một số thuộc tính tuỳ chỉnh để giữ ý định về trải nghiệm chuyển động giảm và trải nghiệm chuyển động đầy đủ. Theo mặc định, các kiểu sẽ giả định rằng người dùng muốn giảm chuyển động, sau đó sử dụng truy vấn nội dung nghe nhìn prefers-reduced-motion để hoán đổi giá trị chuyển đổi thành chuyển động đầy đủ.

Chiến lược giảm chuyển động bằng các thuộc tính tuỳ chỉnh

Ba thuộc tính tuỳ chỉnh được tạo trong CSS sau đây: --_motion-reduced, --_motion-ok--_transition. Hai biến đầu tiên giữ các hiệu ứng chuyển đổi thích hợp dựa trên lựa chọn ưu tiên của người dùng và biến cuối cùng --_transition sẽ được đặt thành --_motion-reduced hoặc --_motion-ok tương ứng.

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

Với những thay đổi trên, bạn có thể chuyển đổi box-shadow, background-color, transformoutline-offset, mang đến cho người dùng phản hồi giao diện người dùng phù hợp rằng họ đã nhận được thông tin tương tác.

Tiếp theo, hãy thêm một chút điểm nhấn cho trạng thái :active bằng cách điều chỉnh translateY một chút. Điều này sẽ tạo cho nút hiệu ứng nhấn đẹp mắt:

.fab {
  

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

Sau đó, chuyển đổi mọi thay đổi đối với các biểu tượng SVG trong nút:

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

Kết luận

Giờ bạn đã biết cách tôi làm, vậy bạn sẽ làm như thế nào‽ 🙂

Hãy đa dạng hoá các phương pháp và tìm hiểu tất cả các cách để xây dựng trên web.

Hãy tạo một bản minh hoạ, gửi đường liên kết cho tôi qua Twitter và tôi sẽ thêm bản minh hoạ đó vào phần bản phối lại của cộng đồng bên dưới!

Bản phối lại của cộng đồng

Chưa có nội dung nào ở đây.

Tài nguyên