Una panoramica di base su come creare componenti FAB adattabili al colore, reattivi e accessibili.
In questo post voglio condividere le mie idee su come creare componenti FAB adattabili al colore, reattivi e accessibili. Prova la demo e visualizza il codice sorgente.
Se preferisci i video, ecco una versione di questo post su YouTube:
Panoramica
I FAB sono più comuni sui dispositivi mobili che sui computer, ma sono prevalenti in entrambi gli scenari. Mantengono in vista le azioni principali, rendendole comode e onnipresenti. Questo stile di esperienza utente è stato reso famoso da Material UI e i relativi suggerimenti per l'utilizzo e il posizionamento sono disponibili qui.
Elementi e stili
Il codice HTML di questi controlli include un elemento contenitore e un insieme di uno o più pulsanti. Il contenitore posiziona i pulsanti di azione rapida all'interno dell'area visibile e gestisce uno spazio tra i pulsanti. I pulsanti possono essere piccoli o predefiniti, offrendo una buona varietà tra azioni principali e secondarie.
Contenitore FAB
Questo elemento può essere un normale <div>
, ma facciamo un favore ai nostri utenti non vedenti
e tagghiamolo con alcuni attributi utili per spiegare lo scopo e i contenuti di
questo contenitore.
Markup dei FAB
Inizia con una classe .fabs
per CSS a cui collegarti per lo stile, poi aggiungi
role="group"
e aria-label
in modo che non sia solo un contenitore generico, ma
denominato e mirato.
<div class="fabs" role="group" aria-label="Floating action buttons">
<!-- buttons will go here -->
</div>
Stile dei FAB
Per essere pratici, i FAB rimangono sempre all'interno dell'area visibile.
Questo è un ottimo caso d'uso per la posizione
fixed
. All'interno di questa
posizione della finestra ho scelto di utilizzare
inset-block
e
inset-inline
in modo che la
posizione si adatti alla modalità del documento dell'utente, ad esempio da destra a sinistra o
da sinistra a destra. Le proprietà personalizzate vengono utilizzate anche per evitare ripetizioni e garantire
una distanza uguale dai bordi inferiore e laterali della finestra.
.fabs {
--_viewport-margin: 2.5vmin;
position: fixed;
z-index: var(--layer-1);
inset-block: auto var(--_viewport-margin);
inset-inline: auto var(--_viewport-margin);
}
Successivamente, assegno al contenitore la visualizzazione
flex
e modifico la
direzione del layout in
column-reverse
.
In questo modo i figli vengono impilati uno sopra l'altro (colonna) e viene invertito anche il loro
ordine visivo. In questo modo, il primo elemento attivabile diventa l'elemento in basso anziché quello in alto, che è la posizione in cui viene normalmente impostato lo stato attivo in base al documento HTML. L'inversione dell'ordine visivo unisce l'esperienza per gli utenti vedenti e per gli utenti che utilizzano la tastiera, in quanto lo stile dell'azione principale più grande dei mini pulsanti indica agli utenti vedenti che si tratta di un'azione principale, mentre gli utenti che utilizzano la tastiera la selezioneranno come primo elemento della sorgente.
.fabs {
…
display: flex;
flex-direction: column-reverse;
place-items: center;
gap: var(--_viewport-margin);
}
La centratura viene gestita con
place-items
e
gap
aggiunge spazio tra i pulsanti
FAB posizionati nel contenitore.
Pulsanti FAB
È il momento di dare uno stile ai pulsanti in modo che sembrino fluttuare sopra ogni cosa.
FAB predefinito
Il primo pulsante da formattare è quello predefinito. che fungerà da base per tutti i pulsanti di azione rapida. In seguito creeremo una variante che ottenga un aspetto alternativo modificando il meno possibile questi stili di base.
Markup FAB
L'elemento <button>
è la scelta giusta. Inizieremo con questa base
perché offre un'ottima esperienza utente con mouse, tocco e tastiera. L'aspetto più
cruciale di questo markup è nascondere l'icona agli utenti di screen reader con
aria-hidden="true"
e aggiungere il testo dell'etichetta necessario al markup <button>
stesso. Quando aggiungo etichette in questi casi, mi piace anche aggiungere un title
in modo che gli utenti che utilizzano il mouse
possano ottenere informazioni su ciò che l'icona vuole comunicare.
<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>
Stile FAB
Innanzitutto, trasformiamo il pulsante in un pulsante rotondo imbottito con un'ombra marcata, in quanto si tratta delle prime caratteristiche che definiscono il pulsante:
.fab {
--_size: 2rem;
padding: calc(var(--_size) / 2);
border-radius: var(--radius-round);
aspect-ratio: 1;
box-shadow: var(--shadow-4);
}
A questo punto, aggiungiamo il colore. Utilizzeremo una strategia che abbiamo già utilizzato in precedenza nelle sfide GUI. Crea un insieme di proprietà personalizzate con un nome chiaro che contengano staticamente i colori chiari e scuri, poi una proprietà personalizzata adattiva che verrà impostata sulle variabili chiare o scure a seconda della preferenza di sistema dell'utente per i colori:
.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);
}
}
Poi aggiungi alcuni stili per adattare le icone SVG allo spazio.
.fab {
…
& > svg {
inline-size: var(--_size);
block-size: var(--_size);
stroke-width: 3px;
}
}
Infine, rimuovi l'evidenziazione del tocco dal pulsante, poiché abbiamo aggiunto un feedback visivo per l'interazione:
.fab {
-webkit-tap-highlight-color: transparent;
}
Mini FAB
L'obiettivo di questa sezione è creare una variante per il pulsante Azione rapida. Rendendo alcuni FAB più piccoli dell'azione predefinita, possiamo promuovere l'azione che l'utente esegue più spesso.
Markup mini FAB
Il codice HTML è lo stesso di un FAB, ma aggiungiamo una classe ".mini" per fornire al CSS un hook nella variante.
<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>
Stile mini FAB
Grazie all'utilizzo delle proprietà personalizzate, l'unica modifica necessaria è un aggiustamento della variabile --_size
.
.fab.mini {
--_size: 1.25rem;
}
Accessibilità
La parte più importante da ricordare per l'accessibilità con i FAB è il posizionamento all'interno del flusso della tastiera della pagina. Questa demo contiene solo i pulsanti di azione rapida, quindi non c'è nulla con cui competere in termini di ordine e flusso della tastiera, il che significa che non ha l'opportunità di dimostrare un flusso della tastiera significativo. In uno scenario in cui sono presenti elementi in competizione per la messa a fuoco, ti suggerisco di riflettere attentamente su quale punto del flusso un utente dovrebbe trovarsi per entrare nel flusso del pulsante FAB.
Una volta che l'utente ha messo a fuoco il contenitore del FAB, abbiamo già aggiunto
role="group"
e aria-label="floating action buttons"
, che informano gli utenti di screen reader sui contenuti su cui hanno messo a fuoco. A livello strategico, ho
posizionato per prima la FAB predefinita, in modo che gli utenti trovino prima l'azione principale. Poi
utilizzo flex-direction: column-reverse;
per ordinare visivamente il pulsante principale
in basso, vicino alle dita degli utenti per un facile accesso. Si tratta di un ottimo risultato
perché il pulsante predefinito è visivamente prominente ed è anche il primo per gli utenti
della tastiera, offrendo loro esperienze molto simili.
Infine, non dimenticare di nascondere le icone agli utenti di screen reader e assicurati di
fornire loro un'etichetta per il pulsante in modo che non sia un mistero. Questa operazione è già stata eseguita nel codice HTML con aria-hidden="true"
su <svg>
e aria-label="Some action"
su <button>
.
Animazione
Per migliorare l'esperienza utente, è possibile aggiungere vari tipi di animazione. Come in
altre sfide della GUI, configureremo un paio di proprietà personalizzate per contenere
l'intento di un'esperienza di movimento ridotto e un'esperienza di movimento completo. Per impostazione predefinita,
gli stili presuppongono che l'utente voglia un movimento ridotto, quindi, utilizzando la
query multimediale prefers-reduced-motion
, scambiano il valore di transizione con il movimento completo.
Una strategia di movimento ridotto con proprietà personalizzate
Nel seguente CSS vengono create tre proprietà personalizzate: --_motion-reduced
,
--_motion-ok
e --_transition
. Le prime due contengono le transizioni appropriate
in base alle preferenze dell'utente, mentre l'ultima variabile --_transition
verrà impostata
su --_motion-reduced
o --_motion-ok
rispettivamente.
.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);
}
}
Con le modifiche sopra descritte, è possibile eseguire la transizione delle modifiche a box-shadow
, background-color
,
transform
e outline-offset
, fornendo all'utente un feedback dell'interfaccia utente
che indica che la sua interazione è stata ricevuta.
Poi, aggiungi un po' di stile allo stato :active
regolando
translateY
leggermente, in modo da dare al pulsante un bell'effetto di pressione:
.fab {
…
&:active {
@media (prefers-reduced-motion: no-preference) {
transform: translateY(2%);
}
}
}
Infine, esegui la transizione di tutte le modifiche alle icone SVG nei pulsanti:
.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);
}
}
}
Conclusione
Ora che sai come ho fatto, come faresti tu?‽ 🙂
Diversifichiamo i nostri approcci e impariamo tutti i modi per creare sul web.
Crea una demo, inviami un tweet con i link e la aggiungerò alla sezione dei remix della community qui sotto.
Remix della community
Ancora nessun elemento da visualizzare.
Risorse
- Codice sorgente su GitHub