Podstawowy przegląd sposobów tworzenia responsywnego, elastycznego i dostępnego komponentu z wieloznacznikiem do sortowania i filtrowania treści.
W tym poście chcę podzielić się z Tobą sposobem tworzenia komponentu z wieloma opcjami wyboru. Wypróbuj wersję demonstracyjną.
Jeśli wolisz film, oto wersja tego posta w YouTube:
Omówienie
Użytkownicy często widzą wiele produktów, a w takich przypadkach warto udostępnić sposób na skrócenie listy, aby zapobiec przeciążeniu wyborem. W tym poście na blogu omawiamy interfejs filtrowania jako sposób na ograniczenie liczby opcji. Robi to, prezentując atrybuty produktów, które użytkownicy mogą zaznaczać lub odznaczać, ograniczając liczbę wyników, a tym samym ograniczając ilość wyborów.
Interakcje
Celem jest umożliwienie szybkiego przeglądania opcji filtrowania wszystkim użytkownikom i przy użyciu różnych typów danych wejściowych. Będzie to możliwe dzięki elastycznej i odpornej parze komponentów. tradycyjny pasek boczny z poleczami wyboru dla komputerów, klawiatur i czytników ekranu oraz <select
multiple>
dla użytkowników urządzeń dotykowych;
Decyzja o użyciu wbudowanego elementu wyboru wielokrotnego w przypadku urządzeń dotykowych, a nie komputerów stacjonarnych, pozwala zaoszczędzić czas i wymaga dodatkowych działań, ale zapewnia odpowiednie działanie przy mniejszym zadłużeniu kodu niż tworzenie całego interfejsu responsywnego w jednym komponencie.
Dotyk
Komponent dotykowy pozwala zaoszczędzić miejsce i ułatwia użytkownikom interakcję na urządzeniach mobilnych. Oszczędza miejsce, ponieważ pozwala zwijać cały pasek boczny z polem wyboru do wbudowanego w interfejs dotykowy <select>
przesłonięcia. Pomaga to w zwiększeniu dokładności wprowadzania danych dzięki wyświetlaniu przez system dużego nakładki dotykowej.
Klawiatura i kontroler
Poniżej znajdziesz demonstrację korzystania z klawisza <select multiple>
na klawiaturze.
Ta wbudowana opcja wyboru wielokrotnego nie może być stylizowana i jest dostępna tylko w kompaktowym układzie, który nie nadaje się do przedstawiania wielu opcji. Widzisz, że w tym małym polu nie widać wszystkich opcji? Chociaż możesz zmienić jego rozmiar, nadal nie jest ono tak wygodne w użyciu jak pasek boczny z poleczami wyboru.
Znacznik
Oba komponenty będą się znajdować w tym samym elemencie <form>
. Wyniki tego formularza, niezależnie od tego, czy są to pola wyboru, czy pola wielokrotnego wyboru, będą obserwowane i używane do filtrowania siatki, ale mogą też zostać przesłane na serwer.
<form>
</form>
Komponent Pola wyboru
Grupy pól wyboru należy umieścić w elementach <fieldset>
i przypisać im etykiety <legend>
.
Gdy kod HTML jest tak sformatowany, czytniki ekranu i FormData automatycznie rozumieją relacje między elementami.
<form>
<fieldset>
<legend>New</legend>
… checkboxes …
</fieldset>
</form>
Po utworzeniu grupowania dodaj <label>
i <input type="checkbox">
do każdego filtra. Ja użyłem elementu <div>
, aby właściwości CSS gap
mogły je równomiernie rozmieszczać i utrzymywać wyrównanie, gdy etykiety będą miały wiele wierszy.
<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>
Komponent <select multiple>
Rzadko używaną funkcją elementu <select>
jest multiple
.
Jeśli atrybut jest używany z elementem <select>
, użytkownik może wybrać wiele elementów z listy. To jak zmiana interakcji z listy rozwijanej na listę z polami wyboru.
<form>
<select multiple="true" title="Filter results by category">
…
</select>
</form>
Aby oznaczyć i utworzyć grupy wewnątrz elementu <select>
, użyj elementu <optgroup>
i przypisz mu atrybut label
oraz wartość. Ten element i wartość atrybutu są podobne do elementów <fieldset>
i <legend>
.
<form>
<select multiple="true" title="Filter results by category">
<optgroup label="New">
…
</optgroup>
</select>
</form>
Teraz dodaj elementy <option>
do filtra.
<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>
Śledzenie danych wejściowych za pomocą liczników w celu informowania technologii wspomagających
W tym przypadku stosujemy technikę statusu roli, aby śledzić i utrzymywać liczbę filtrów dla czytników ekranu i innych technologii wspomagających. Film w YouTube demonstrujący tę funkcję. Integracja zaczyna się od kodu HTML i atrybutu role="status"
.
<div role="status" class="sr-only" id="applied-filters"></div>
Ten element odczyta na głos zmiany wprowadzone w treści. Możemy aktualizować zawartość za pomocą liczników CSS, gdy użytkownicy będą korzystać z pól wyboru. W tym celu musimy najpierw utworzyć licznik z nazwą w elemencie nadrzędnym elementów wejściowych i elementu stanu.
aside {
counter-reset: filters;
}
Domyślna liczba to 0
, co jest świetne, ponieważ w tym przypadku nic nie jest domyślnie :checked
.
Następnie, aby zwiększyć wartość nowo utworzonego licznika, będziemy kierować reklamy na elementy podrzędne elementu <aside>
, które są elementami :checked
. Gdy użytkownik zmienia stan danych wejściowych, licznik filters
będzie się zwiększał.
aside :checked {
counter-increment: filters;
}
CSS wie teraz, że ogólna liczba pól wyboru w interfejsie jest równa 0, a element stanu role jest pusty i oczekuje na wartości. Ponieważ CSS przechowuje wynik w pamięci, funkcja counter()
umożliwia dostęp do wartości z zawartości elementu pseudo:
aside #applied-filters::before {
content: counter(filters) " filters ";
}
Kod HTML elementu roli stanu będzie teraz ogłaszać w narzędziach do odczytu ekranu „2 filtry”. To dobry początek, ale możemy zrobić więcej, np. udostępnić podsumowanie wyników zaktualizowanych przez filtry. Wykorzystamy do tego JavaScript, ponieważ nie można tego zrobić za pomocą liczników.
Tworzenie emocji
Algorytm liczników świetnie współpracował z CSS nesting-1, ponieważ udało mi się umieścić całą logikę w jednym bloku. Przenośna i scentralizowana funkcja odczytu i aktualizowania.
aside {
counter-reset: filters;
& :checked {
counter-increment: filters;
}
& #applied-filters::before {
content: counter(filters) " filters ";
}
}
Układy
W tej sekcji opisujemy układy między tymi 2 komponentami. Większość stylów układu dotyczy komponentu pola wyboru na komputerze.
Formularz
Aby zoptymalizować czytelność i możliwość szybkiego przeglądania przez użytkowników, formularz ma maksymalną szerokość 30 znaków, co w podstawie ustawia szerokość linii optycznej dla każdej etykiety filtra. Formularz używa układu siatki i właściwości gap
, aby rozmieszczać pola danych w odstępach.
form {
display: grid;
gap: 2ch;
max-inline-size: 30ch;
}
Element <select>
Lista etykiet i pola wyboru zajmują zbyt dużo miejsca na urządzeniach mobilnych. Dlatego układ sprawdza, jakie urządzenie wskazujące jest używane przez użytkownika, aby zmienić sposób obsługi dotykowej.
@media (pointer: coarse) {
select[multiple] {
display: block;
}
}
Wartość coarse
oznacza, że użytkownik nie będzie mógł sterować ekranem z dużą precyzją za pomocą głównego urządzenia wejściowego. Na urządzeniu mobilnym wartość wskaźnika często wynosi coarse
, ponieważ główną metodą interakcji jest dotyk. Na komputerze wartość wskaźnika często wynosi fine
, ponieważ często podłączona jest mysz lub inne urządzenie wejściowe o wysokiej precyzji.
Pola zbiorcze
Domyślny styl i układ <fieldset>
z <legend>
są unikalne:
Zazwyczaj, aby rozmieścić elementy podrzędne, używam właściwości gap
, ale unikalne pozycjonowanie elementu <legend>
utrudnia tworzenie równomiernie rozmieszczonych elementów podrzędnych. Zamiast gap
używane są selektor sąsiedniego elementu siostrzanego i margin-block-start
.
fieldset {
padding: 2ch;
& > div + div {
margin-block-start: 2ch;
}
}
W tym przypadku nie trzeba dostosowywać miejsca na <legend>
, ponieważ kierujemy reklamy tylko do dzieci (<div>
).
Etykieta filtra i pole wyboru
Jako element podrzędny elementu <fieldset>
i mieszczący się w maksymalnej szerokości elementu 30ch
w formularzu tekst etykiety może się zawijać, jeśli jest zbyt długi. Zawijanie tekstu jest świetne, ale niedopasowanie między tekstem a polem wyboru nie. Do tego celu idealnie nadaje się flexbox.
fieldset > div {
display: flex;
gap: 2ch;
align-items: baseline;
}
Animowana siatka
Animację układu wykonuje Isotope. Wydajny i wydajny wtyczka do interaktywnego sortowania i filtrowania.
JavaScript
Oprócz pomocy w zarządzaniu przejrzystą, animowaną i interaktywną siatką JavaScript służy też do dopieszczania szczegółów.
Normalizacja danych wejściowych użytkownika
Ten projekt ma 1 formularz z 2 różnymi sposobami wprowadzania danych, które nie są serializowane. Jednak za pomocą kodu JavaScript możemy normalizować dane.
Zdecydowaliśmy się dopasować strukturę danych elementu <select>
do struktury pól wyboru w grupach. W tym celu do elementu <select>
dodawany jest detektor zdarzenia input
, który jest następnie mapowany na element selectedOptions
.
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
}, [])
})
Teraz możesz bezpiecznie przesłać formularz lub, w przypadku tego demonstracyjnego projektu, poinformować Isotope, według jakich kryteriów ma być przeprowadzany filtr.
Zakończenie elementu roli stanu
Element zlicza i podaje liczbę filtrów tylko na podstawie interakcji z polem wyboru, ale uznaliśmy, że warto dodatkowo udostępnić liczbę wyników i upewnić się, że uwzględnione są też elementy <select>
.
Wybór elementu <select>
odzwierciedlony w elementach counter()
W sekcji normalizacji danych na podstawie danych wejściowych został już utworzony odbiorca. Na końcu tej funkcji znana jest liczba wybranych filtrów i liczba wyników dla tych filtrów. Wartości można przekazywać do elementu roli stanu w ten sposób:
let statusRoleElement = document.querySelector('#applied-filters')
statusRoleElement.style.counterSet = selectData.length
Wyniki odzwierciedlone w elemencie role="status"
:checked
zapewnia wbudowany sposób przekazywania liczby wybranych filtrów do elementu roli stanu, ale nie zapewnia widoczności dla przefiltrowanej liczby wyników.
Kod JavaScript może sprawdzać interakcje z polami wyboru i po odfiltrowaniu siatki dodawać textContent
, tak jak to robi element <select>
.
document
.querySelector('aside form')
.addEventListener('input', e => {
// isotope demo code
let filterResults = IsotopeGrid.getFilteredItemElements().length
document.querySelector('#applied-filters').textContent = `giving ${filterResults} results`
})
W ten sposób zakończymy wprowadzanie zmian związanych z ogłoszeniem „2 filtry, które dają 25 wyników”.
Teraz wszyscy użytkownicy będą mogli korzystać z naszej doskonałej technologii wspomagającej.
Podsumowanie
Teraz, gdy już wiesz, jak to zrobić, jak Ty to zrobisz? 🙂
Zróżnicujemy nasze podejścia i poznamy wszystkie sposoby tworzenia stron internetowych. Utwórz wersję demonstracyjną, wyślij mi linki, a ja dodam je do sekcji z remiksami społeczności.
Remiksy społeczności
Na razie jest tu pusto