Tworzenie komponentu pływającego przycisku polecenia (FAB)

Podstawowe informacje o tym, jak tworzyć komponenty FAB dostosowujące się do koloru, responsywne i dostępne.

W tym poście chcę podzielić się moimi przemyśleniami na temat tworzenia komponentów FAB, które dostosowują się do kolorów, są responsywne i dostępne. Wypróbuj wersję demonstracyjnąwyświetl kod źródłowy.

Jeśli wolisz film, obejrzyj tę wersję posta w YouTube:

Przegląd

Przyciski FAB są częściej używane na urządzeniach mobilnych niż na komputerach, ale występują w obu tych przypadkach. Główne działania są zawsze widoczne, co sprawia, że są wygodne i wszechobecne. Ten styl interfejsu użytkownika został spopularyzowany przez Material UI, a ich sugestie dotyczące użycia i umiejscowienia można znaleźć tutaj.

Elementy i style

Kod HTML tych elementów sterujących obejmuje element kontenera i zestaw co najmniej 1 przycisku. Kontener umieszcza przyciski FAB w widocznym obszarze i zarządza odstępem między nimi. Przyciski mogą być małe lub domyślne, co zapewnia dużą różnorodność między działaniami głównymi i dodatkowymi.

Kontener FAB

Ten element może być zwykłym elementem <div>, ale zróbmy coś dobrego dla użytkowników, którzy nie widzą, i dodajmy do niego przydatne atrybuty, aby wyjaśnić jego przeznaczenie i zawartość.

Znaczniki przycisków FAB

Zacznij od klasy .fabs, aby CSS mógł się do niej odwoływać w celu nadania stylu, a następnie dodaj role="group"aria-label, aby nie był to tylko ogólny kontener, ale miał nazwę i określone przeznaczenie.

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

Styl przycisków FAB

Aby przyciski FAB były wygodne w użyciu, muszą być zawsze widoczne w widocznym obszarze. To świetny przypadek użycia dla parametru position fixed. W tym obszarze widoku wybrałem inset-blockinset-inline, aby pozycja była zgodna z trybem dokumentu użytkownika, np. od prawej do lewej lub od lewej do prawej. Właściwości niestandardowe są też używane, aby zapobiegać powtórzeniom i zapewniać równą odległość od dolnej i bocznych krawędzi obszaru widocznego:

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

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

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

Następnie nadaję kontenerowi właściwość display flex i zmieniam kierunek układu na column-reverse. Spowoduje to ułożenie elementów podrzędnych jeden na drugim (w kolumnie), a także odwrócenie ich kolejności wizualnej. Sprawia to, że pierwszym elementem, który można zaznaczyć, jest element dolny, a nie górny, na którym zwykle znajduje się fokus zgodnie z dokumentem HTML. Odwrócenie kolejności wizualnej ujednolica działanie dla użytkowników widzących i korzystających z klawiatury, ponieważ stylizacja działania głównego jako większego niż miniaturowe przyciski wskazuje użytkownikom widzącym, że jest to działanie główne, a użytkownicy korzystający z klawiatury skupią się na nim jako na pierwszym elemencie w źródle.

Widoczne są 2 przyciski FAB, a na ich układ siatki nałożone są Narzędzia deweloperskie. Pokazuje odstęp między nimi w postaci wzoru w paski, a także obliczoną wysokość i szerokość.

.fabs {
  

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

Wyśrodkowanie jest obsługiwane przez place-items, a gap dodaje odstęp między przyciskami FAB umieszczonymi w kontenerze.

Przyciski FAB

Czas ostylować przyciski tak, aby wyglądały, jakby unosiły się nad wszystkim.

Domyślny FAB

Pierwszym przyciskiem, który możesz ostylować, jest przycisk domyślny. Będzie to podstawa wszystkich przycisków FAB. Później utworzymy wariant, który będzie miał inny wygląd, ale zmodyfikujemy w nim jak najmniej tych podstawowych stylów.

Znaczniki FAB

Element <button> jest prawidłową odpowiedzią. Zaczniemy od tej wersji, ponieważ zapewnia ona wygodną obsługę za pomocą myszy, dotyku i klawiatury. Najważniejszym aspektem tego znacznika jest ukrycie ikony przed użytkownikami czytników ekranu za pomocą atrybutu aria-hidden="true" i dodanie niezbędnego tekstu etykiety do samego znacznika <button>. W takich przypadkach lubię też dodawać etykiety z symbolem title, aby użytkownicy myszy mogli uzyskać informacje o tym, co ma przekazywać ikona.

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

Styl FAB

Najpierw przekształćmy przycisk w zaokrąglony przycisk z wypełnieniem i wyraźnym cieniem, ponieważ są to pierwsze cechy definiujące przycisk:

.fab {
  --_size: 2rem;

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

Teraz dodajmy kolor. Zastosujemy strategię, której używaliśmy już wcześniej w przypadku wyzwań związanych z GUI. Utwórz wyraźnie nazwany zestaw właściwości niestandardowych, które statycznie przechowują jasne i ciemne kolory, a następnie adaptacyjną właściwość niestandardową, która będzie ustawiana na zmienne jasne lub ciemne w zależności od preferencji użytkownika dotyczących kolorów w systemie:

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

Następnie dodaj style, aby ikony SVG pasowały do przestrzeni.

.fab {
  

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

Na koniec usuń podświetlenie kliknięcia przycisku, ponieważ dodaliśmy własną wizualną informację zwrotną dotyczącą interakcji:

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

Miniprzycisk typu FAB

Celem tej sekcji jest utworzenie wariantu przycisku FAB. Zmniejszając niektóre przyciski FAB w stosunku do domyślnego działania, możemy promować działanie, które użytkownik wykonuje najczęściej.

Znaczniki miniprzycisku typu FAB

Kod HTML jest taki sam jak w przypadku przycisku FAB, ale dodajemy klasę „.mini”, aby umożliwić CSS dostęp do wariantu.

<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>
Styl miniprzycisku FAB

Dzięki użyciu właściwości niestandardowych jedyną zmianą, jaką należy wprowadzić, jest dostosowanie zmiennej --_size.

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

Zrzut ekranu przedstawiający 2 przyciski pływające ułożone jeden na drugim. Górny przycisk jest mniejszy od dolnego.

Ułatwienia dostępu

Najważniejszą kwestią, o której należy pamiętać w przypadku ułatwień dostępu do przycisków FAB, jest ich umiejscowienie w przepływie klawiatury na stronie. Ta wersja demonstracyjna zawiera tylko przyciski FAB. Nie ma w niej nic, co mogłoby konkurować z kolejnością i przepływem klawiatury, co oznacza, że nie ma możliwości zademonstrowania znaczącego przepływu klawiatury. W sytuacji, gdy o skupienie uwagi użytkownika konkurują różne elementy, warto się zastanowić, w którym momencie procesu użytkownik powinien przejść do korzystania z przycisku FAB.

Demonstracja interakcji z klawiaturą

Gdy użytkownik skupi się na kontenerze FAB, dodamy już elementy role="group"aria-label="floating action buttons", które informują użytkowników czytników ekranu o zawartości elementu, na którym się skupili. Strategicznie umieściłem domyślny przycisk FAB na pierwszym miejscu, aby użytkownicy najpierw znaleźli główną czynność. Następnie używam flex-direction: column-reverse;, aby wizualnie uporządkować główny przycisk u dołu, blisko palców użytkowników, co ułatwia dostęp. To dobra wiadomość, ponieważ domyślny przycisk jest dobrze widoczny i jako pierwszy pojawia się w przypadku użytkowników klawiatury, co zapewnia im bardzo podobne wrażenia.

Nie zapomnij też ukryć ikon przed użytkownikami czytników ekranu i zapewnić im etykiety przycisków, aby nie były dla nich zagadką. Zostało to już zrobione w HTML-u za pomocą aria-hidden="true" w przypadku <svg>aria-label="Some action" w przypadku <button>.

Animacja

Aby poprawić wrażenia użytkowników, można dodać różne rodzaje animacji. Podobnie jak w przypadku innych wyzwań związanych z GUI skonfigurujemy kilka właściwości niestandardowych, aby określić intencję związaną z efektem ograniczonego ruchu i efektem pełnego ruchu. Domyślnie style będą zakładać, że użytkownik chce ograniczyć ruch, a następnie za pomocą zapytania o media prefers-reduced-motion zamienią wartość przejścia na pełny ruch.

Strategia ograniczonego ruchu z właściwościami niestandardowymi

W tym kodzie CSS tworzone są 3 niestandardowe właściwości: --_motion-reduced, --_motion-ok i --_transition. Pierwsze 2 zmienne zawierają odpowiednie przejścia w zależności od preferencji użytkownika, a ostatnia zmienna --_transition będzie miała wartość --_motion-reduced lub --_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);
  }
}

Dzięki temu można wprowadzać zmiany w box-shadow, background-color, transformoutline-offset, co zapewnia użytkownikowi odpowiednie informacje zwrotne w interfejsie, że jego interakcja została zarejestrowana.

Następnie dodaj nieco więcej stylu do stanu :active, wprowadzając niewielkie zmianytranslateY. Dzięki temu przycisk będzie wyglądał jak wciśnięty:

.fab {
  

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

Na koniec wprowadź zmiany w ikonach SVG w przyciskach:

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

Podsumowanie

Teraz, gdy wiesz, jak to zrobiłem, jak Ty byś to zrobił? 🙂

Urozmaićmy nasze podejście i poznajmy wszystkie sposoby tworzenia treści w internecie.

Utwórz demo, wyślij mi na Twitterze linki, a ja dodam je do sekcji remiksów społeczności poniżej.

Remiksy społeczności

Na razie jest tu pusto.

Zasoby