نظرة عامة أساسية حول كيفية إنشاء مكوّن متعدد الاختيارات متجاوب وقابل للتكيّف وسهل الاستخدام من أجل تصنيف تجارب المستخدمين وفلترتها
في هذه المشاركة، أريد مشاركة أفكار حول طريقة إنشاء مكوّن اختيار متعدّد. جرِّب الإصدار التجريبي.
إذا كنت تفضّل الفيديو، يمكنك الاطّلاع على نسخة من هذا المنشور على YouTube:
نظرة عامة
غالبًا ما يتم عرض عناصر على المستخدمين، وفي بعض الأحيان العديد من العناصر، وفي هذه الحالات، قد يكون من المفيد توفير طريقة لتقليل القائمة لتجنّب الشعور بالارتباك بسبب كثرة الخيارات. تتناول مشاركة المدونة هذه واجهة مستخدم الفلترة كطريقة لتقليل الخيارات. ويتم ذلك من خلال عرض سمات السلع التي يمكن للمستخدمين اختيارها أو إلغاء اختيارها، ما يؤدي إلى تقليل النتائج وبالتالي تقليل عدد الخيارات المعروضة.
التفاعلات
والهدف من ذلك هو السماح بالتنقّل السريع بين خيارات الفلترة لجميع المستخدمين و
أنواع الإدخال المختلفة. سيتم عرض هذا المحتوى باستخدام
مكوّنَين قابلَين للتكيّف والتوافق مع مختلف الأجهزة. شريط جانبي تقليدي يتضمّن مربّعات اختيار لأجهزة الكمبيوتر المكتبي ولوحة المفاتيح
وتطبيقات قراءة الشاشة، و<select
multiple>
لمستخدمي الأجهزة التي تعمل باللمس
إنّ قرار استخدام ميزة "الاختيار المتعدّد" المضمّنة للأجهزة التي تعمل باللمس وليس لأجهزة الكمبيوتر المكتبي يوفر الجهد ويخلق العمل، ولكنّني أعتقد أنّه يقدّم تجارب مناسبة بأقل قدر من رموز الترميز مقارنةً بإنشاء تجربة الاستجابة الكاملة في مكوّن واحد.
اللمس
يوفر مكوّن اللمس مساحة ويساعد في دقة تفاعل المستخدم على
الأجهزة الجوّالة. ويساعد ذلك في توفير المساحة من خلال تصغير شريط جانبي كامل من مربّعات الاختيار إلى
<select>
تجربة لمس مدمجة. ويساعد ذلك في دقة الإدخال من خلال عرض
تجربة كبيرة للشاشة التي تعمل باللمس يوفّرها النظام.
لوحة المفاتيح وجهاز التحكّم في الألعاب
في ما يلي عرض توضيحي لكيفية استخدام <select multiple>
من لوحة المفاتيح.
لا يمكن وضع تنسيق على ميزة الاختيار المتعدّد المضمّنة هذه، ولا تتوفّر إلا بتنسيق ملف شخصي محدود غير مناسب لعرض الكثير من الخيارات. هل يمكنك رؤية مدى اتّساع الخيارات في هذا المربّع الصغير؟ على الرغم من أنّه يمكنك تغيير حجمه، فإنه لا يزال أقل سهولة في الاستخدام من الشريط الجانبي الذي يتضمّن مربّعات اختيار.
Markup
سيتم تضمين كلا المكوّنين في عنصر <form>
نفسه. سيتم رصد نتائج
هذا النموذج، سواء كانت مربّعات اختيار أو قائمة اختيار متعدّدة، واستخدامها لfiltrare الشبكة، ولكن يمكن أيضًا إرسالها إلى خادم.
<form>
</form>
مكوّن مربّعات الاختيار
يجب تضمين مجموعات مربّعات الاختيار في عنصر
<fieldset>
ومنحهم علامة
<legend>
.
عند تنظيم صفحات HTML بهذه الطريقة، سيفهم قارئ الشاشة وFormData تلقائيًا علاقة العناصر.
<form>
<fieldset>
<legend>New</legend>
… checkboxes …
</fieldset>
</form>
بعد تطبيق التجميع، أضِف <label>
و<input type="checkbox">
لكل من الفلاتر. اخترتُ لفّ تصنيفي في <div>
حتى تتمكّن خاصية gap
في CSS
من توزيعها بالتساوي والحفاظ على المحاذاة عندما تكون التصنيفات متعددة الأسطر.
<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>
من الميزات التي نادرًا ما يتم استخدامها في عنصر <select>
هي
multiple
.
عند استخدام السمة مع عنصر <select>
، يُسمح للمستخدم بتحديد
العديد من القيم من القائمة. يشبه ذلك تغيير التفاعل من قائمة خيارات متناوبة
إلى قائمة مربّعات اختيار.
<form>
<select multiple="true" title="Filter results by category">
…
</select>
</form>
لتصنيف المجموعات وإنشائها داخل <select>
، استخدِم العنصر
<optgroup>
وأضِف إليه سمة label
وقيمة. هذا العنصر والسمة
القيمة مشابهان للعنصرَين <fieldset>
و<legend>
.
<form>
<select multiple="true" title="Filter results by category">
<optgroup label="New">
…
</optgroup>
</select>
</form>
أضِف الآن عناصر
<option>
للفلتر.
<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>
تتبُّع الإدخال باستخدام العدّادات لتوفير معلومات للتكنولوجيا المساعِدة
يتم استخدام أسلوب حالة
دور
في تجربة المستخدم هذه لتتبُّع عدد
الفلاتر لبرامج قراءة الشاشة والتقنيات المساعِدة الأخرى والحفاظ عليه. يوضّح فيديو YouTube
كيفية استخدام هذه الميزة. يبدأ الدمج بتنسيق HTML والسمة
role="status"
.
<div role="status" class="sr-only" id="applied-filters"></div>
سيقرأ هذا العنصر التغييرات التي تم إجراؤها على المحتوى بصوت عالٍ. يمكننا تعديل المحتوى باستخدام عدادات CSS عندما يتفاعل المستخدمون مع مربّعات الاختيار. لإجراء ذلك، يجب أولاً إنشاء ملف شخصي يحتوي على اسم في عنصر رئيسي للعناصر inputs وstate.
aside {
counter-reset: filters;
}
سيكون العدد تلقائيًا 0
، وهو أمر رائع، لأنّه ليس هناك أي :checked
تلقائيًا في هذا التصميم.
بعد ذلك، لزيادة المعداد الذي تم إنشاؤه حديثًا، سنستهدف العناصر الفرعية لعنصر
<aside>
التي تكون :checked
. وعندما يغيّر المستخدم حالة الإدخالات،
سيتم احتساب عدد العناصر في filters
.
aside :checked {
counter-increment: filters;
}
يعلم CSS الآن بالعدد الإجمالي لواجهة مستخدم مربّع الاختيار ويكون عنصر دور الحالة
فارغًا في انتظار القيم. بما أنّ CSS تحافظ على الاحتساب في
الذاكرة، تسمح الدالة
counter()
بالوصول إلى القيمة من محتويات العنصر
الزائف:
aside #applied-filters::before {
content: counter(filters) " filters ";
}
سيعرض رمز HTML لعنصر دور الحالة الآن "فلتران " لجهاز قراءة الشاشة. هذه بداية جيدة، ولكن يمكننا تحسينها، مثلاً من خلال مشاركة عدد النتائج التي عدّلت الفلاتر. سننفّذ هذا العمل من JavaScript، لأنّه خارج نطاق ما يمكن أن تُنفّذه العدّادات.
إثارة الدمج
كانت خوارزمية العدّادات رائعة مع CSS التداخل-1، لأنّني تمكّنت من وضع كل المنطق في كتلة واحدة. شعور بالسهولة في نقل البيانات وتعديلها
aside {
counter-reset: filters;
& :checked {
counter-increment: filters;
}
& #applied-filters::before {
content: counter(filters) " filters ";
}
}
التنسيقات
يوضّح هذا القسم التنسيقات بين المكوّنين. معظم أنماط التنسيق مخصّصة لمكوّن مربّع الاختيار على أجهزة الكمبيوتر المكتبي.
النموذج
لتحسين سهولة القراءة والاطّلاع على النموذج، يتم ضبط عرضه على 30 حرفًا بحد أقصى، ما يؤدي إلى ضبط عرض السطر البصري لكل تصنيف فلتر. يستخدم النموذج تنسيق الشبكة والسمة gap
لترك مسافة بين
حقول المجموعة.
form {
display: grid;
gap: 2ch;
max-inline-size: 30ch;
}
العنصر <select>
تستهلك قائمة التصنيفات مربّعات الاختيار مساحة كبيرة جدًا على الأجهزة الجوّالة. لذلك، يتحقّق التنسيق من جهاز الإشارة الأساسي للمستخدم لتغيير تجربة اللمس.
@media (pointer: coarse) {
select[multiple] {
display: block;
}
}
تشير القيمة coarse
إلى أنّ المستخدم لن يتمكّن من التفاعل مع
الشاشة بدقة عالية باستخدام جهاز الإدخال الأساسي. على
الأجهزة الجوّالة، غالبًا ما تكون قيمة المؤشر هي coarse
، لأنّ التفاعل الأساسي
يكون من خلال اللمس. على جهاز كمبيوتر مكتبي، غالبًا ما تكون قيمة المؤشر هي fine
لأنّه من الشائع
أن يكون هناك ماوس أو جهاز إدخال آخر عالي الدقة متصلاً.
مجموعات الحقول
النمط والتصميم التلقائيان لرمز <fieldset>
مع <legend>
هما فريدان:
عادةً، سأستخدم السمة gap
لإضافة مسافة بين العناصر الفرعية، ولكن يصعّب الوضع الفريد
لعنصر <legend>
إنشاء مجموعة متساوية المسافة
للعناصر الفرعية. بدلاً من gap
، يتم استخدام أداة اختيار الشقيق المجاور وmargin-block-start
.
fieldset {
padding: 2ch;
& > div + div {
margin-block-start: 2ch;
}
}
يؤدي ذلك إلى عدم تعديل مساحة <legend>
من خلال استهداف
<div>
الأطفال فقط.
تصنيف الفلتر ومربّع الاختيار
بصفتها عنصرًا ثانويًا مباشرًا للعنصر <fieldset>
وضمن الحد الأقصى لعرض
30ch
النموذج، قد يتمّ التفاف نص التصنيف إذا كان طويلاً جدًا. إنّ لفّ النص أمر رائع، ولكن
عدم محاذاة النص مربّع الاختيار ليس كذلك. ويعدّ Flexbox مثاليًا لهذا الغرض.
fieldset > div {
display: flex;
gap: 2ch;
align-items: baseline;
}

الشبكة المتحركة
يتم إنشاء الرسوم المتحركة للتخطيط بواسطة Isotope. مكوّن إضافي فعال وفعّال للفلترة والترتيب التفاعليَين
JavaScript
بالإضافة إلى المساعدة في تنظيم شبكة تفاعلية متحركة وأنيقة، يتم استخدام JavaScript لتحسين بعض الجوانب.
تطبيع إدخال المستخدم
يتضمّن هذا التصميم نموذجًا واحدًا بطريقتَين مختلفتَين لتقديم الإدخال، وهما لا تتم تسلسل بنفس الطريقة. باستخدام بعض رموز JavaScript، يمكننا تسويتها.
اخترت مواءمة بنية بيانات العنصر <select>
مع بنية مربّعات الاختيار المُجمَّعة. لإجراء ذلك، تتم إضافة أداة معالجة حدث
input
إلى عنصر <select>
، وعند هذه النقطة تتم معالجة
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
}, [])
})
يمكنك الآن إرسال النموذج بأمان، أو في ما يتعلّق بهذا العرض الترويجي، يمكنك توجيه Isotope بشأن ما تريد الفلترة حسبه.
إنهاء عنصر دور الحالة
لا يحتسب العنصر عدد الفلاتر ويعلن عنه إلا استنادًا إلى تفاعل مربّع الاختيار، ولكنني أعتقد أنّه من المفيد أيضًا مشاركة عدد
النتائج والتأكّد من احتساب خيارات عنصر <select>
أيضًا.
اختيار عنصر <select>
يظهر في counter()
في قسم تطبيع البيانات، سبق أن تم إنشاء مستمع عند الإدخال. في نهاية هذه الدالة، يكون عدد الفلاتر التي تم اختيارها وعدد النتائج لهذه الفلاتر معروفًا. يمكن تمرير القيم إلى عنصر دور الحالة على النحو التالي.
let statusRoleElement = document.querySelector('#applied-filters')
statusRoleElement.style.counterSet = selectData.length
النتائج المعروضة في عنصر role="status"
يوفّر :checked
طريقة مضمّنة لنقل عدد الفلاتر المحدّدة إلى
عنصر دور الحالة، ولكنّه لا يقدّم إمكانية الوصول إلى العدد الذي تمّت فلترته من النتائج.
يمكن لـ JavaScript مراقبة التفاعل مع مربّعات الاختيار وبعد فلترة الجدول، إضافة textContent
مثل العنصر <select>
.
document
.querySelector('aside form')
.addEventListener('input', e => {
// isotope demo code
let filterResults = IsotopeGrid.getFilteredItemElements().length
document.querySelector('#applied-filters').textContent = `giving ${filterResults} results`
})
يكمل هذا العمل الإعلان "فلتران يقدّمان 25 نتيجة".
ستتوفّر الآن تجربة التكنولوجيا المساعِدة الممتازة لجميع المستخدمين، بغض النظر عن طريقة تفاعلهم معها.
الخاتمة
الآن بعد أن عرفت كيف فعلت ذلك، كيف ستفعل ذلك؟ 🙂
لننوّع أساليبنا ونتعرّف على جميع الطرق لإنشاء تطبيقات على الويب. أنشئ عرضًا توضيحيًا وأرسِل إلينا رابطًا على Twitter، وسنضيفه إلى قسم الريمكسات التي أنشأها المستخدمون أدناه.
الريمكسات التي أنشأها المستخدمون
ما مِن عناصر للاطّلاع عليها هنا حتى الآن.