نظرة عامة أساسية حول كيفية إنشاء مكوّن اختيار متعدّد متجاوب وقابل للتكيّف وسهل الاستخدام لتصنيف تجارب المستخدمين وفلترتها
في هذه المشاركة، أريد مشاركة أفكار حول طريقة إنشاء مكوّن اختيار متعدّد. جرِّب الإصدار التجريبي.
إذا كنت تفضّل مشاهدة الفيديوهات، يمكنك الاطّلاع على نسخة من هذه المشاركة على 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، وسنضيفه إلى قسم الريمكسات التي أنشأها المستخدمون أدناه.
الريمكسات التي أنشأها المستخدمون
ما مِن عناصر للاطّلاع عليها هنا حتى الآن.