Una panoramica di base su come creare componenti FAB adattabili al colore, reattivi e accessibili.
In questo post voglio condividere la mia opinione 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
Le FAB sono più comuni sui dispositivi mobili che sui computer, ma sono prevalenti in entrambi gli scenari. Mantengono visibili le azioni principali, rendendole comode e omnipresenti. Questo stile di esperienza utente è stato reso famoso da Material UI e i suoi suggerimenti per l'utilizzo e il posizionamento sono disponibili qui.
Elementi e stili
Il codice HTML di questi controlli prevede un elemento contenitore e un insieme di uno o più pulsanti. Il contenitore posiziona i FAB all'interno dell'area visibile e gestisce un spazio tra i pulsanti. I pulsanti possono essere mini o predefiniti, offrendo una buona varietà tra le azioni principali e secondarie.
Contenitore FAB
Questo elemento può essere un normale <div>
, ma facciamo un favore ai nostri utenti non vedenti e etichettiamolo con alcuni attributi utili per spiegare lo scopo e i contenuti di questo contenitore.
Markup delle FAB
Inizia con una classe .fabs
a cui il CSS può collegarsi per lo stile, quindi aggiungi role="group"
e aria-label
in modo che non sia solo un contenitore generico, ma sia nominato e intenzionale.
<div class="fabs" role="group" aria-label="Floating action buttons">
<!-- buttons will go here -->
</div>
Stile delle FAB
Per essere pratici, i pulsanti flottanti rimangono sempre nell'area visibile.
Questo è un ottimo caso d'uso per la posizione
fixed
. In questa
posizione del viewport ho scelto di utilizzare
inset-block
e
inset-inline
in modo che la
posizione sia in linea con la 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 la stessa distanza dai bordi inferiore e laterali della visualizzazione:
.fabs {
--_viewport-margin: 2.5vmin;
position: fixed;
z-index: var(--layer-1);
inset-block: auto var(--_viewport-margin);
inset-inline: auto var(--_viewport-margin);
}
Poi associo al contenitore il display
flex
e ne modifico la
direzione del layout in
column-reverse
.
In questo modo, gli elementi secondari vengono impilati uno sopra l'altro (colonna) e viene invertito anche il loro ordine visivo. Questo ha l'effetto di rendere il primo elemento attivabile l'elemento inferiore anziché quello superiore, che è dove lo stato attivo viene normalmente impostato nel documento HTML. L'inversione dell'ordine visivo unisce l'esperienza per gli utenti vedenti e quelli che usano la tastiera, poiché lo stile dell'azione principale è più grande dei mini pulsanti e indica agli utenti vedenti che si tratta di un'azione principale, mentre gli utenti che usano la tastiera la metteranno a fuoco come primo elemento nell'origine.
.fabs {
…
display: flex;
flex-direction: column-reverse;
place-items: center;
gap: var(--_viewport-margin);
}
Il centratura viene gestita con
place-items
e
gap
aggiunge spazio tra i pulsanti
FAB posizionati nel contenitore.
Pulsanti FAB
È il momento di dare stile ad alcuni pulsanti in modo che sembrino galleggiare sopra a tutto.
Pulsante flottante predefinito
Il primo pulsante da applicare è il pulsante predefinito. che fungerà da base per tutti i pulsanti FAB. In seguito creeremo una variante che offre un aspetto alternativo, modificando il meno possibile questi stili di base.
Markup FAB
L'elemento <button>
è la scelta giusta. Inizieremo da qui come base
perché offre un'esperienza utente ottimale con mouse, tocco e tastiera. L'aspetto più importante 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 aggiungi etichette in questi casi, mi piace anche aggiungere un title
in modo che gli utenti che usano 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
Per prima cosa, trasformiamo il pulsante in un pulsante arrotondato con una forte ombra, poiché si tratta delle prime caratteristiche che lo definiscono:
.fab {
--_size: 2rem;
padding: calc(var(--_size) / 2);
border-radius: var(--radius-round);
aspect-ratio: 1;
box-shadow: var(--shadow-4);
}
Aggiungiamo il colore. Utilizzeremo una strategia già utilizzata in precedenza nelle sfide GUI. Crea un insieme di proprietà personalizzate denominate in modo chiaro che contengono in modo statico i colori chiari e scuri, quindi 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);
}
}
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 il nostro feedback visivo per l'interazione:
.fab {
-webkit-tap-highlight-color: transparent;
}
Mini FAB
Lo scopo di questa sezione è creare una variante per il pulsante FAB. 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 punto di contatto con la 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 FAB mini
Grazie all'utilizzo delle proprietà personalizzate, l'unica modifica necessaria è un aggiustamento della variabile --_size
.
.fab.mini {
--_size: 1.25rem;
}
Accessibilità
L'aspetto 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 FAB, non c'è concorrenza in termini di ordine e flusso della tastiera, il che significa che non ha l'opportunità di dimostrare un flusso della tastiera significativo. In un scenario in cui sono presenti elementi in competizione per l'attenzione, ti consiglio di riflettere attentamente su dove in quel flusso un utente dovrebbe trovarsi a entrare nel flusso del pulsante FAB.
Una volta che l'utente ha attivato il contenitore FAB, abbiamo già aggiunto role="group"
e aria-label="floating action buttons"
per informare gli utenti dello screen reader sui contenuti su cui hanno attivato la funzionalità. Per motivi strategici, ho collocato prima il FAB predefinito, in modo che gli utenti trovino prima l'azione principale. Poi uso flex-direction: column-reverse;
per disporre visivamente il pulsante principale in basso, vicino alle dita dell'utente per un facile accesso. Si tratta di un risultato positivo
perché il pulsante predefinito è in evidenza e viene visualizzato per primo per gli utenti
con tastiera, offrendo loro esperienze molto simili.
Infine, non dimenticare di nascondere le icone agli utenti che utilizzano screen reader e assicurati di fornire loro un'etichetta per il pulsante in modo che non sia un mistero. Questo è stato già fatto in HTML con aria-hidden="true"
per <svg>
e aria-label="Some action"
per i <button>
.
Animazione
È possibile aggiungere vari tipi di animazioni per migliorare l'esperienza utente. Come in altre sfide GUI, configureremo un paio di proprietà personalizzate per contenere lo scopo di un'esperienza con movimento ridotto e un'esperienza con movimento completo. Per impostazione predefinita, gli stili presuppongono che l'utente voglia ridurre il movimento, quindi utilizzando la query media prefers-reduced-motion
scambia 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 e l'ultima variabile --_transition
verrà impostata rispettivamente su --_motion-reduced
o --_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);
}
}
Con quanto sopra, è possibile eseguire la transizione delle modifiche a box-shadow
, background-color
,
transform
e outline-offset
, fornendo all'utente un feedback sull'interfaccia utente che indica che la sua interazione è stata ricevuta.
Aggiungi un po' di stile allo stato :active
modificando leggermente translateY
, 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 eventuali 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? 🙂
Diversifichiamo i nostri approcci e impariamo tutti i modi per creare sul web.
Crea una demo, twittami i link e io la aggiungerò alla sezione dei remix della community di seguito.
Remix della community
Ancora nessun elemento da visualizzare.
Risorse
- Codice sorgente su GitHub