Una panoramica di base su come creare un componente reattivo, adattivo, accessibile e a selezione multipla per ordinare e filtrare le esperienze utente.
In questo post voglio condividere le idee su come creare un componente a selezione multipla. Prova la demo.
Se preferisci i video, ecco una versione di questo post su YouTube:
Panoramica
Agli utenti vengono spesso presentati alcuni elementi, a volte molti, e in queste casi, potrebbe essere una buona idea fornire un modo per ridurre l'elenco per evitare sovraccarico di scelta. Questo post del blog esplora l'applicazione di filtri all'interfaccia utente per ridurre le scelte. Per farlo, presentando attributi degli articoli che gli utenti possono selezionare o deselezionare, riducendo i risultati riducendo il sovraccarico di opzioni.
Interazioni
L'obiettivo è consentire il trasferimento rapido delle opzioni di filtro per tutti gli utenti e i loro
tipi di input diversi. con una presentazione adattabile e adattabile
coppia di componenti. Una tradizionale barra laterale di caselle di controllo per desktop, tastiera
e screen reader, oltre a una <select
multiple>
per gli utenti touch.
La decisione di utilizzare la selezione multipla integrata per il tocco e non per il desktop consente di risparmiare lavoro e crea lavoro, ma credo che offra esperienze appropriate con un debito di codice inferiore rispetto a creare l'intera esperienza reattiva in un solo componente.
Tocco
Il componente touch consente di risparmiare spazio e aiuta l'utente a interagire con la massima precisione
mobile. Consente di risparmiare spazio comprimendo un'intera barra laterale di caselle di controllo
Esperienza touch overlay integrata di <select>
. Migliora la precisione dell'input mostrando
un ampio overlay touch fornito dal sistema.
Tastiera e gamepad
Di seguito è riportata una dimostrazione di come utilizzare <select multiple>
dalla tastiera.
Questa selezione multipla integrata non può essere adattata allo stile ed è offerta solo in una versione compatta non adatto a presentare molte opzioni. Scopri come non è possibile vedere l'ampia gamma di opzioni in quella piccola casella? Anche se puoi modificarne le dimensioni, ancora non utilizzabili come barre laterali di caselle di controllo.
Aumento
Entrambi i componenti saranno contenuti nello stesso elemento <form>
. I risultati di
questo modulo, che si tratti di caselle di controllo o selezione multipla, verrà osservato e utilizzato per
filtrare la griglia, ma potrebbero anche essere inviate a un server.
<form>
</form>
Componente Caselle di controllo
I gruppi di caselle di controllo devono essere racchiusi in una
<fieldset>
e viene fornito un
<legend>
.
Quando l'HTML è strutturato in questo modo, gli screen reader e
FormData
a comprendere automaticamente la relazione degli elementi.
<form>
<fieldset>
<legend>New</legend>
… checkboxes …
</fieldset>
</form>
Con il raggruppamento attivo, aggiungi <label>
e <input type="checkbox">
per
per ciascuno dei filtri. Ho scelto di aggregare il mio file in <div>
, quindi la proprietà gap
del CSS
possono distribuirle uniformemente e mantenere l'allineamento quando le etichette sono su più righe.
<form>
<fieldset>
<legend>New</legend>
<div>
<input type="checkbox" id="last 30 days" name="new" value="last 30 days">
<label for="last 30 days">Last 30 Days</label>
</div>
<div>
<input type="checkbox" id="last 6 months" name="new" value="last 6 months">
<label for="last 6 months">Last 6 Months</label>
</div>
</fieldset>
</form>
<select multiple>
componente
Una funzionalità raramente utilizzata dell'elemento <select>
è
multiple
Quando l'attributo viene utilizzato con un elemento <select>
, l'utente può:
e sceglierli dall'elenco. È come modificare l'interazione da un elenco di segnali radio
a un elenco di caselle di controllo.
<form>
<select multiple="true" title="Filter results by category">
…
</select>
</form>
Per etichettare e creare gruppi all'interno di un <select>
, utilizza le
<optgroup>
e assegnargli un attributo e un valore label
. Questo elemento e questo attributo
sono simili agli elementi <fieldset>
e <legend>
.
<form>
<select multiple="true" title="Filter results by category">
<optgroup label="New">
…
</optgroup>
</select>
</form>
Ora aggiungi il
<option>
per il filtro.
<form>
<select multiple="true" title="Filter results by category">
<optgroup label="New">
<option value="last 30 days">Last 30 Days</option>
<option value="last 6 months">Last 6 Months</option>
</optgroup>
</select>
</form>
Monitoraggio degli input con i contatori per informare sulle tecnologie per la disabilità
Lo stato
ruolo
tecnica utilizzata in questa esperienza utente, per monitorare e mantenere
filtri per screen reader e altre tecnologie per la disabilità. Il video di YouTube
illustra la caratteristica. L'integrazione inizia con il codice HTML e l'attributo
role="status"
.
<div role="status" class="sr-only" id="applied-filters"></div>
Questo elemento leggerà ad alta voce le modifiche apportate ai contenuti. Possiamo aggiornare contenuti con CSS contatori man mano che gli utenti interagiscono con le caselle di controllo. Per farlo dobbiamo prima creare un contatore con un nome su un elemento principale degli input e dell'elemento di stato.
aside {
counter-reset: filters;
}
Per impostazione predefinita, il conteggio sarà 0
, il che è ottimo, niente è :checked
per
per impostazione predefinita.
Successivamente, per aumentare il contatore appena creato, sceglieremo come target gli elementi secondari dei
Elemento <aside>
che corrisponde a :checked
. Quando l'utente cambia lo stato degli input,
il contatore filters
verrà conteggiato.
aside :checked {
counter-increment: filters;
}
Ora CSS è a conoscenza del conteggio generale dell'interfaccia utente della casella di controllo e del ruolo dello stato
è vuoto e in attesa di valori. Dal momento che il CSS mantiene il punteggio in
la memoria,
counter()
consente di accedere al valore da pseudo
Element:
aside #applied-filters::before {
content: counter(filters) " filters ";
}
L'HTML per l'elemento status role annuncerà "2 filtri" a una schermata Reader. È un buon inizio, ma possiamo fare di meglio, ad esempio condividiamo il conteggio risultati aggiornati dei filtri. Lo faremo da JavaScript, poiché al di fuori di ciò che possono fare i contatori.
Emozioni per nidificare
L'algoritmo dei contatori ha trovato molto interessanti con CSS nesting-1, dato che ho potuto inserire tutti la logica in un blocco. Per la lettura e l'aggiornamento è portatile e centralizzato.
aside {
counter-reset: filters;
& :checked {
counter-increment: filters;
}
& #applied-filters::before {
content: counter(filters) " filters ";
}
}
Layout
Questa sezione descrive i layout tra i due componenti. La maggior parte gli stili di layout sono destinati al componente casella di controllo desktop.
Il modulo
Per ottimizzare la leggibilità e la leggibilità per gli utenti, al modulo viene assegnato un massimo
di 30 caratteri, impostando essenzialmente una larghezza ottica delle linee
sull'etichetta del filtro. Il modulo utilizza il layout a griglia e la proprietà gap
per distribuire la
set di campi.
form {
display: grid;
gap: 2ch;
max-inline-size: 30ch;
}
Elemento <select>
L'elenco di etichette e caselle di controllo occupano troppo spazio sui dispositivi mobili. Di conseguenza, il layout verifica che il dispositivo di puntamento principale dell'utente venga modificato per l'esperienza touch.
@media (pointer: coarse) {
select[multiple] {
display: block;
}
}
Il valore coarse
indica che l'utente non potrà interagire con
schermo con un'elevata precisione
con il dispositivo di input principale. Su un
dispositivo mobile, il valore del puntatore è spesso coarse
, come interazione principale
è tocco. Su un computer, il valore del puntatore è spesso fine
in quanto è comune
di avere collegato un mouse o un altro dispositivo di input ad alta precisione.
I set di campi
Lo stile e il layout predefiniti di <fieldset>
con <legend>
sono univoci:
Normalmente, per distribuire gli elementi secondari utilizzerei la proprietà gap
, ma l'attributo
la posizione dell'elemento <legend>
rende difficile la creazione di un set a spaziatura uniforme
dei bambini. Invece di gap
, l'elemento di pari livello adiacente
selettore e
margin-block-start
.
fieldset {
padding: 2ch;
& > div + div {
margin-block-start: 2ch;
}
}
In questo modo, <legend>
non può modificare lo spazio utilizzando come target solo
<div>
minori.
L'etichetta del filtro e la casella di controllo
Come elemento secondario diretto di un <fieldset>
e entro la larghezza massima del valore
30ch
, il testo dell'etichetta potrebbe andare a capo se troppo lungo. La disposizione del testo a capo
va bene,
il disallineamento tra testo e casella di controllo non lo è. Flexbox è l'ideale.
fieldset > div {
display: flex;
gap: 2ch;
align-items: baseline;
}
La griglia animata
L'animazione del layout è eseguita da Isotope. R dalle prestazioni elevate per l'ordinamento e il filtro interattivi.
JavaScript
Oltre ad aiutare a orchestrare una griglia animata e interattiva, in tempo reale viene usato per lucidare un paio di bordi grezzi.
Normalizzare l'input utente
Questo design ha un unico modulo con due diversi modi per fornire input. non devi serie il modello in modo analogo. Con un po' di codice JavaScript, però, normalizzare i dati.
Ho scelto di allineare la struttura dei dati dell'elemento <select>
alle caselle di controllo raggruppate
alla struttura del centro di costo. Per fare ciò,
input
all'elemento <select>
viene aggiunto un listener di eventi, dopodiché viene
selectedOptions
vengono mappati.
document.querySelector('select').addEventListener('input', event => {
// make selectedOptions iterable then reduce a new array object
let selectData = Array.from(event.target.selectedOptions).reduce((data, opt) => {
// parent optgroup label and option value are added to the reduce aggregator
data.push([opt.parentElement.label.toLowerCase(), opt.value])
return data
}, [])
})
Ora puoi inviare il modulo in sicurezza oppure, nel caso di questa demo, dare istruzioni a Isotope in base ai quali filtrare.
Completamento dell'elemento "Status Role" in corso...
L'elemento conteggia e annuncia il conteggio dei filtri solo in base alla casella di controllo
interazione, ma ho trovato una buona idea condividere anche il numero di
e garantire che vengano conteggiate anche le scelte dell'elemento <select>
.
La scelta dell'elemento <select>
si riflette in counter()
Nella sezione di normalizzazione dei dati, è già stato creato un listener nell'input. Alle ore alla fine di questa funzione il numero di filtri scelti e il numero di risultati per questi filtri sono noti. I valori possono essere passati all'elemento "State Role" in questo modo.
let statusRoleElement = document.querySelector('#applied-filters')
statusRoleElement.style.counterSet = selectData.length
Risultati riportati nell'elemento role="status"
:checked
offre un modo integrato per passare il numero di filtri scelti a
l'elemento status role, ma manca di visibilità per il numero di risultati filtrati.
JavaScript può rilevare l'interazione con le caselle di controllo e, dopo aver applicato un filtro al
griglia, aggiungi textContent
come ha fatto l'elemento <select>
.
document
.querySelector('aside form')
.addEventListener('input', e => {
// isotope demo code
let filterResults = IsotopeGrid.getFilteredItemElements().length
document.querySelector('#applied-filters').textContent = `giving ${filterResults} results`
})
Nel complesso questo lavoro completa l'annuncio "2 filtri che danno 25 risultati".
Ora la nostra eccellente esperienza relativa alle tecnologie per la disabilità sarà disponibile per tutti ma gli utenti vi interagiscono.
Conclusione
Ora che sai come ci ho fatto, come faresti‽ 🙂
Diversificaamo i nostri approcci e impariamo tutti i modi per creare sul web. Crea una demo, twittami con i link e la aggiungerò alla sezione dei remix della community qui sotto.
Remix della community
Ancora niente da visualizzare qui.