Çoklu seçim bileşeni oluşturma

Sıralama ve filtreleme kullanıcı deneyimleri için duyarlı, uyarlanabilir ve erişilebilir bir çoklu seçim bileşeni oluşturma hakkında temel bilgiler.

Bu yayında, çoklu seçim bileşeni oluşturma yöntemleriyle ilgili düşüncelerimi paylaşmak istiyorum. Demoyu deneyin.

Demo

Video tercih ediyorsanız bu yayının YouTube versiyonunu aşağıda bulabilirsiniz:

Genel Bakış

Kullanıcılara genellikle öğeler, bazen de çok sayıda öğe sunulur. Bu durumlarda, seçenek bolluğunu önlemek için listeyi azaltmanın bir yolunu sunmak iyi bir fikir olabilir. Bu blog yayınında, seçenekleri azaltmanın bir yolu olarak filtreleme kullanıcı arayüzü ele alınmaktadır. Bu işlem, kullanıcıların seçebileceği veya seçimini kaldırabileceği öğe özelliklerini sunarak yapılır. Böylece sonuç sayısı ve dolayısıyla seçenek fazlalığı azaltılır.

Etkileşimler

Amaç, tüm kullanıcıların ve farklı giriş türlerinin filtre seçenekleri arasında hızlıca gezinmesini sağlamaktır. Bu, uyarlanabilir ve duyarlı bir bileşen çiftiyle birlikte sunulur. Masaüstü, klavye ve ekran okuyucular için onay kutularının bulunduğu geleneksel bir kenar çubuğu, dokunmatik kullanıcılar için ise <select multiple>.

Masaüstü açık ve koyu temayı, onay kutularının bulunduğu bir kenar çubuğuyla karşılaştıran ekran görüntüsü. Mobil iOS ve Android&#39;de ise çoklu seçim öğesi gösteriliyor.

Dokunma için yerleşik çoklu seçim özelliğini kullanma ve masaüstü için kullanmama kararı, iş yükünü azaltır ve artırır ancak tüm duyarlı deneyimi tek bir bileşende oluşturmaya kıyasla daha az kod borcuyla uygun deneyimler sunduğunu düşünüyorum.

Dokunma

Dokunma bileşeni, alandan tasarruf etmenizi sağlar ve mobil cihazlarda kullanıcı etkileşiminin doğruluğuna yardımcı olur. Tüm onay kutularının bulunduğu kenar çubuğunu <select> yerleşik bir yer paylaşımı dokunma deneyimine daraltarak yer tasarrufu sağlar. Sistem tarafından sağlanan büyük bir dokunma katmanı deneyimi göstererek giriş doğruluğuna yardımcı olur.

Android, iPhone ve iPad&#39;de Chrome&#39;daki çoklu seçim öğesinin ekran görüntüsü önizlemesi. iPad ve iPhone&#39;da çoklu seçim özelliği açık durumdadır ve her biri ekran boyutuna göre optimize edilmiş benzersiz bir deneyim sunar.

Klavye ve oyun kumandası

Klavyeden <select multiple> nasıl kullanılacağına dair bir gösterimi aşağıda bulabilirsiniz.

Bu yerleşik çoklu seçim özelliği stilize edilemez ve yalnızca çok sayıda seçeneğin sunulması için uygun olmayan kompakt bir düzende sunulur. O küçük kutuda seçeneklerin tamamını göremediğinizi fark ettiniz mi? Boyutunu değiştirebilirsiniz ancak yine de onay kutularının bulunduğu bir kenar çubuğu kadar kullanışlı değildir.

Brüt kar

Her iki bileşen de aynı <form> öğesinde yer alır. Bu formun sonuçları (onay kutuları veya çoklu seçim) gözlemlenir ve ızgarayı filtrelemek için kullanılır ancak bir sunucuya da gönderilebilir.

<form>

</form>

Onay kutuları bileşeni

Onay kutusu grupları bir <fieldset> öğesine sarılmalı ve <legend> verilmelidir. HTML bu şekilde yapılandırıldığında, ekran okuyucular ve FormData, öğelerin ilişkisini otomatik olarak anlar.

<form>
  <fieldset>
    <legend>New</legend>
    … checkboxes …
  </fieldset>
</form>

Gruplandırma yapıldıktan sonra her filtre için <label> ve <input type="checkbox"> ekleyin. CSS gap özelliği, etiketler çok satırlı olduğunda aralarındaki boşluğu eşit şekilde dağıtıp hizalamayı koruyabilsin diye etiketlerimi <div> içine almayı tercih ettim.

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

Açıklama ve alan kümesi öğeleri için bilgilendirici bir yer paylaşımı içeren ekran görüntüsünde renk ve öğe adı gösteriliyor.

<select multiple> bileşeni

<select> öğesinin nadiren kullanılan bir özelliği multiple. Özellik bir <select> öğesiyle kullanıldığında kullanıcının listeden birden fazla seçenek belirlemesine izin verilir. Etkileşimi radyo listesinden onay kutusu listesine değiştirmeye benzer.

<form>
  <select multiple="true" title="Filter results by category">
    …
  </select>
</form>

<select> içinde grupları etiketlemek ve oluşturmak için <optgroup> öğesini kullanın ve bu öğeye label özelliği ve değeri verin. Bu öğe ve özellik değeri, <fieldset> ve <legend> öğelerine benzer.

<form>
  <select multiple="true" title="Filter results by category">
    <optgroup label="New">
      …
    </optgroup>
  </select>
</form>

Şimdi filtre için <option> öğelerini ekleyin.

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

Çoklu seçim öğesinin masaüstü oluşturma işleminin ekran görüntüsü.

Yardımcı teknolojilere bilgi vermek için sayaçlarla girişi izleme

Bu kullanıcı deneyiminde, ekran okuyucular ve diğer yardımcı teknolojiler için filtrelerin sayısını izlemek ve korumak amacıyla durum rolü tekniği kullanılır. YouTube videosunda özellik gösteriliyor. Entegrasyon, HTML ve role="status" özelliğiyle başlar.

<div role="status" class="sr-only" id="applied-filters"></div>

Bu öğe, içeriklerde yapılan değişiklikleri sesli okur. Kullanıcılar onay kutularıyla etkileşimde bulundukça CSS sayaçları ile içerikleri güncelleyebiliriz. Bunu yapmak için öncelikle girişlerin ve durum öğesinin üst öğesinde ad içeren bir sayaç oluşturmamız gerekir.

aside {
  counter-reset: filters;
}

Varsayılan olarak sayı 0 olur. Bu harika bir durumdur. Bu tasarımda varsayılan olarak hiçbir şey :checked değildir.

Ardından, yeni oluşturduğumuz sayacı artırmak için <aside> öğesinin :checked olan alt öğelerini hedefleyeceğiz. Kullanıcı girişlerin durumunu değiştirdikçe filters sayacı artar.

aside :checked {
  counter-increment: filters;
}

CSS artık onay kutusu kullanıcı arayüzünün genel sayısını biliyor ve durum rolü öğesi boş olup değerleri bekliyor. CSS, toplamı bellekte tuttuğundan counter() işlevi, değeri sözde öğe içeriklerinden erişmeye olanak tanır:

aside #applied-filters::before {
  content: counter(filters) " filters ";
}

Durum rolü öğesinin HTML'si artık ekran okuyucuya "2 filtre" olarak okunacak. Bu iyi bir başlangıç olsa da filtrelerin güncellediği sonuçların sayısını paylaşmak gibi daha iyi bir çözüm sunabiliriz. Sayaçların yapabileceklerinin dışında olduğundan bu işlemi JavaScript'ten yapacağız.

MacOS ekran okuyucusunun etkin filtre sayısını duyurduğu ekranın görüntüsü.

Yuva yapma heyecanı

Sayaç algoritması, tüm mantığı tek bir blokta toplayabildiğim için CSS nesting-1 ile harika çalıştı. Okuma ve güncelleme için taşınabilir ve merkezi bir deneyim sunar.

aside {
  counter-reset: filters;

  & :checked {
    counter-increment: filters;
  }

  & #applied-filters::before {
    content: counter(filters) " filters ";
  }
}

Düzenler

Bu bölümde, iki bileşen arasındaki düzenler açıklanmaktadır. Çoğu düzen stili, masaüstü onay kutusu bileşeni içindir.

Form

Kullanıcılar için okunabilirliği ve taranabilirliği optimize etmek amacıyla forma maksimum 30 karakter genişlik verilir. Bu sayede, her filtre etiketi için optik bir satır genişliği belirlenir. Formda, alan kümeleri arasında boşluk bırakmak için ızgara düzeni ve gap özelliği kullanılıyor.

form {
  display: grid;
  gap: 2ch;
  max-inline-size: 30ch;
}

<select> öğesi

Etiket listesi ve onay kutuları mobil cihazda çok fazla yer kaplıyor. Bu nedenle, düzen, dokunma deneyimini değiştirmek için kullanıcının birincil işaretleme cihazını kontrol eder.

@media (pointer: coarse) {
  select[multiple] {
    display: block;
  }
}

coarse değeri, kullanıcının birincil giriş cihazıyla ekrana yüksek hassasiyetle dokunamayacağını gösterir. Bir mobil cihazda, birincil etkileşim dokunma olduğu için işaretçi değeri genellikle coarse olur. Masaüstü cihazlarda, fare veya başka bir yüksek hassasiyetli giriş cihazı bağlı olması yaygın olduğundan işaretçi değeri genellikle fine olur.

Alan kümeleri

<legend> içeren bir <fieldset> öğesinin varsayılan stili ve düzeni benzersizdir:

Bir alan kümesi ve açıklama için varsayılan stillerin ekran görüntüsü.

Normalde alt öğelerimi aralandırmak için gap özelliğini kullanırdım ancak <legend> öğesinin benzersiz konumlandırması, eşit aralıklı bir alt öğe grubu oluşturmayı zorlaştırıyor. gap yerine adjacent sibling selector ve margin-block-start kullanılır.

fieldset {
  padding: 2ch;

  & > div + div {
    margin-block-start: 2ch;
  }
}

Bu, yalnızca <div> alt öğeleri hedeflenerek <legend> öğesinin alanının ayarlanmasını atlar.

Girişler arasındaki kenar boşluğu aralığını gösteren ancak lejendi göstermeyen ekran görüntüsü.

Filtre etiketi ve onay kutusu

<fieldset> öğesinin doğrudan alt öğesi olarak ve formun 30ch maksimum genişliği içinde yer alan etiket metni çok uzunsa kaydırılabilir. Metni kaydırmak harika bir özellik olsa da metin ve onay kutusu arasındaki hizalama hatası iyi bir özellik değildir. Bu işlem için Flexbox idealdir.

fieldset > div {
  display: flex;
  gap: 2ch;
  align-items: baseline;
}
Onay işaretinin, çok satırlı sarmalama senaryosunda metnin ilk satırıyla nasıl hizalandığını gösteren ekran görüntüsü.
Bu Codepen'de daha fazla oynayın

Animasyonlu ızgara

Düzen animasyonu Isotope tarafından yapılır. Etkileşimli sıralama ve filtreleme için yüksek performanslı ve güçlü bir eklenti.

JavaScript

JavaScript, düzenli bir animasyonlu ve etkileşimli ızgaranın düzenlenmesine yardımcı olmanın yanı sıra birkaç pürüzü gidermek için de kullanılır.

Kullanıcı girişini normalleştirme

Bu tasarımda, giriş sağlamanın iki farklı yolunu içeren bir form vardır ve bunlar aynı şekilde serileştirilmez. Ancak bazı JavaScript'lerle verileri normalleştirebiliriz.

Hedefi ve normalleştirilmiş veri sonuçlarını gösteren DevTools JavaScript konsolunun ekran görüntüsü.

<select> öğe veri yapısını, gruplandırılmış onay kutuları yapısıyla eşleştirmeyi seçtim. Bunu yapmak için <select> öğesine bir input etkinlik işleyici eklenir. Bu noktada selectedOptions eşlenir.

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
  }, [])
})

Artık formu gönderebilirsiniz veya bu demoda olduğu gibi Isotope'a neye göre filtreleme yapacağını söyleyebilirsiniz.

Durum rolü öğesini tamamlama

Öğe yalnızca onay kutusu etkileşimine göre filtre sayısını hesaplayıp duyuruyor ancak sonuç sayısını da paylaşmanın ve <select> öğe seçimlerinin de sayılmasını sağlamanın iyi bir fikir olduğunu düşündüm.

<select> öğe seçimi counter() içinde yansıtılır

Veri normalleştirme bölümünde, girişte zaten bir dinleyici oluşturulmuştu. Bu işlevin sonunda, seçilen filtrelerin sayısı ve bu filtrelerle ilgili sonuçların sayısı bilinir. Değerler, durum rolü öğesine şu şekilde iletilebilir.

let statusRoleElement = document.querySelector('#applied-filters')
statusRoleElement.style.counterSet = selectData.length

Sonuçlar role="status" öğesine yansıtılır.

:checked, seçilen filtrelerin sayısını durum rolü öğesine iletmek için yerleşik bir yöntem sunar ancak filtrelenen sonuç sayısının görünürlüğü yoktur. JavaScript, onay kutularıyla etkileşimi izleyebilir ve ızgarayı filtreledikten sonra textContent öğesi gibi <select> ekleyebilir.

document
  .querySelector('aside form')
  .addEventListener('input', e => {
    // isotope demo code
    let filterResults = IsotopeGrid.getFilteredItemElements().length
    document.querySelector('#applied-filters').textContent = `giving ${filterResults} results`
})

Bu çalışma, "2 filtre 25 sonuç veriyor" duyurusunu tamamlıyor.

MacOS ekran okuyucusunun sonuçları duyurduğu ekranın görüntüsü.

Artık mükemmel yardımcı teknoloji deneyimimiz, kullanıcılar nasıl etkileşim kurarsa kursun tüm kullanıcılara sunulacak.

Sonuç

Bunu nasıl yaptığımı öğrendiğinize göre, siz nasıl yapardınız? 🙂

Yaklaşımlarımızı çeşitlendirelim ve web'de içerik oluşturmanın tüm yollarını öğrenelim. Bir demo oluşturun, bağlantıları bana tweet atın. Ben de bu bağlantıları aşağıdaki topluluk remiksleri bölümüne ekleyeyim.

Topluluk remiksleri

Henüz burada gösterilecek bir şey yok.