نظرة عامة أساسية حول كيفية إنشاء شريط جانبي قابل للانزلاق وسريع الاستجابة
في هذه المشاركة، أريد أن أشارك معك كيفية إنشاء نموذج أولي لمكوّن Sidenav للويب يكون سريع الاستجابة ويحتفظ بالحالة ويدعم التنقّل باستخدام لوحة المفاتيح ويعمل مع JavaScript وبدونه، ويتوافق مع جميع المتصفّحات. جرِّب الإصدار التجريبي.
إذا كنت تفضّل مشاهدة الفيديوهات، يمكنك الاطّلاع على نسخة من هذه المشاركة على YouTube:
نظرة عامة
من الصعب إنشاء نظام تنقّل سريع الاستجابة. سيستخدم بعض المستخدمين لوحة مفاتيح، وسيكون لدى البعض أجهزة كمبيوتر مكتبية قوية، وسيستخدم البعض الآخر جهازًا جوّالاً صغيرًا. يجب أن يتمكّن جميع الزوّار من فتح القائمة وإغلاقها.
Web Tactics
في استكشاف المكوّنات هذا، كان من دواعي سروري الجمع بين بعض الميزات المهمة لمنصّة الويب:
- CSS
:target
- شبكة CSS
- عمليات التحويل في CSS
- طلبات CSS Media Queries لإطار العرض والإعدادات المفضّلة للمستخدم
- JavaScript
focus
لتحسينات تجربة المستخدم
يتضمّن الحلّ الذي أقدّمه شريطًا جانبيًا واحدًا ولا يتم تفعيله إلا عند عرض الصفحة على إطار "شاشة جهاز جوّال" أبعاده 540px
أو أقل.
ستكون 540px
نقطة التوقف للتبديل بين التنسيق التفاعلي للأجهزة الجوّالة والتنسيق الثابت لأجهزة الكمبيوتر المكتبي.
الفئة الصورية :target
في CSS
يضبط أحد الروابط <a>
تجزئة عنوان URL على #sidenav-open
والآخر على فارغ (''
).
أخيرًا، يحتوي العنصر على id
لمطابقة التجزئة:
<a href="#sidenav-open" id="sidenav-button" title="Open Menu" aria-label="Open Menu">
<a href="#" id="sidenav-close" title="Close Menu" aria-label="Close Menu"></a>
<aside id="sidenav-open">
…
</aside>
يؤدي النقر على كلٍّ من هذين الرابطَين إلى تغيير حالة علامة التجزئة لعنوان URL للصفحة، ثم باستخدام فئة زائفة، أعرض شريط التنقّل الجانبي وأخفيه:
@media (max-width: 540px) {
#sidenav-open {
visibility: hidden;
}
#sidenav-open:target {
visibility: visible;
}
}
شبكة CSS
في السابق، كنت أستخدم فقط تصاميم ومكونات شريط التنقّل الجانبي في موضع مطلق أو ثابت. ومع ذلك، تتيح لنا شبكة البيانات، باستخدام بنية grid-area
،
تخصيص عناصر متعددة للصف أو العمود نفسه.
الحِزم
عنصر التنسيق الأساسي #sidenav-container
هو شبكة تنشئ صفًا واحدًا وعمودَين، ويُطلق على أحدهما اسم stack
. عندما تكون المساحة محدودة، تحدّد CSS اسم الشبكة نفسه لجميع عناصر <main>
التابعة، ما يؤدي إلى وضع جميع العناصر في المساحة نفسها وإنشاء حزمة.
#sidenav-container {
display: grid;
grid: [stack] 1fr / min-content [stack] 1fr;
min-height: 100vh;
}
@media (max-width: 540px) {
#sidenav-container > * {
grid-area: stack;
}
}
خلفية القائمة
<aside>
هو العنصر المتحرّك الذي يحتوي على شريط التنقّل الجانبي. يحتوي على
عنصرَين فرعيَّين: حاوية التنقّل <nav>
التي تحمل الاسم [nav]
وخلفية <a>
التي تحمل الاسم [escape]
، والتي تُستخدَم لإغلاق القائمة.
#sidenav-open {
display: grid;
grid-template-columns: [nav] 2fr [escape] 1fr;
}
عدِّل 2fr
و1fr
للعثور على النسبة التي تفضّلها للعنصر المتراكب للقوائم وزر الإغلاق في المساحة السلبية.
عمليات التحويل والانتقالات الثلاثية الأبعاد في CSS
تم تجميع التنسيق الآن بحجم إطار عرض للأجهزة الجوّالة. إلى أن أضيف بعض الأنماط الجديدة، سيتمّ وضعها فوق المقالة تلقائيًا. في ما يلي بعض ميزات تجربة المستخدم التي أسعى إلى تحقيقها في هذا القسم التالي:
- إضافة تأثيرات متحركة للفتح والإغلاق
- استخدام الصور المتحركة فقط إذا كان المستخدم موافقًا على ذلك
- تحريك
visibility
لكي لا ينتقل تركيز لوحة المفاتيح إلى العنصر الذي لا يظهر على الشاشة
عندما أبدأ في تنفيذ الرسوم المتحركة، أريد التركيز على تسهيل الاستخدام.
مؤثرات حركية يسهل فهمها
قد لا يرغب بعض المستخدمين في تجربة انزلاق المحتوى للخارج. في الحلّ الذي نقدّمه، يتم تطبيق هذه الإعدادات المفضّلة
من خلال تعديل متغيّر --duration
في CSS داخل طلب بحث الوسائط. تمثّل قيمة طلب البحث عن الوسائط هذه
الإعدادات المفضّلة لنظام التشغيل الخاص بالمستخدم في ما يتعلّق بالحركة (إذا كان ذلك متاحًا).
#sidenav-open {
--duration: .6s;
}
@media (prefers-reduced-motion: reduce) {
#sidenav-open {
--duration: 1ms;
}
}
الآن عندما يتم فتح شريط التنقّل الجانبي وإغلاقه، إذا كان المستخدم يفضّل تقليل الحركة، أنقل العنصر على الفور إلى العرض، مع الحفاظ على الحالة بدون حركة.
الانتقال والتحويل والترجمة
شريط التنقّل الجانبي خارج الشاشة (تلقائي)
لضبط الحالة التلقائية للشريط الجانبي على الأجهزة الجوّالة على أنّها حالة "خارج الشاشة"،
أضع العنصر باستخدام transform: translateX(-110vw)
.
يُرجى العِلم أنّني أضفت 10vw
آخر إلى رمز -100vw
المعتاد الذي يظهر خارج الشاشة،
لضمان عدم ظهور box-shadow
في شريط التنقّل الجانبي في مساحة العرض الرئيسية عندما يكون مخفيًا.
@media (max-width: 540px) {
#sidenav-open {
visibility: hidden;
transform: translateX(-110vw);
will-change: transform;
transition:
transform var(--duration) var(--easeOutExpo),
visibility 0s linear var(--duration);
}
}
شريط التنقّل الجانبي في
عندما يتطابق عنصر #sidenav
مع :target
، اضبط موضع translateX()
على قاعدة العرض 0
،
وراقِب CSS وهي تُزِل العنصر من موضع "الخارج" -110vw
إلى موضع "الداخل"
0
على var(--duration)
عند تغيير تجزئة عنوان URL.
@media (max-width: 540px) {
#sidenav-open:target {
visibility: visible;
transform: translateX(0);
transition:
transform var(--duration) var(--easeOutExpo);
}
}
إذن الوصول إلى الانتقال
والهدف الآن هو إخفاء القائمة من تطبيقات قراءة الشاشة عندما تكون مضمّنة،
كي لا تركّز الأنظمة على قائمة خارج الشاشة. وأتمكّن من إجراء ذلك من خلال ضبط انتقال
مستوى الرؤية عند تغيير :target
.
- عند الانتقال إلى العنصر، يجب أن يكون مرئيًا على الفور حتى أتمكّن من رؤية العنصر ينزلق إلى الداخل وقبول التركيز عليه.
- عند الخروج، يمكنك تغيير مستوى العرض ولكن مع تأخيره، بحيث يتحول إلى
hidden
في نهاية عملية الخروج.
تحسينات على تجربة المستخدم في أدوات تسهيل الاستخدام
الروابط
يعتمد هذا الحل على تغيير عنوان URL لإدارة الحالة.
من الطبيعي أن يتم استخدام العنصر <a>
هنا، ويحصل على بعض ميزات تسهيل الاستخدام
مجانًا. لنضيف إلى عناصرنا التفاعلية تصنيفات توضّح الغرض منها بوضوح.
<a href="#" id="sidenav-close" title="Close Menu" aria-label="Close Menu"></a>
<a href="#sidenav-open" id="sidenav-button" class="hamburger" title="Open Menu" aria-label="Open Menu">
<svg>...</svg>
</a>
توضِّح الآن أزرار التفاعل الأساسية الغرض منها بوضوح لكل من الماوس ولوحة المفاتيح.
:is(:hover, :focus)
يتيح لنا هذا العنصر الاختياري الوهمي الوظيفي لخدمة مقارنة الأسعار (CSS) أن نوفّر ميزات شاملة بسرعة من خلال أنماط التمرير فوق العناصر من خلال مشاركتها مع التركيز أيضًا.
.hamburger:is(:hover, :focus) svg > line {
stroke: hsl(var(--brandHSL));
}
استخدام JavaScript
اضغط على escape
للإغلاق
من المفترض أن يؤدي الضغط على مفتاح Escape
في لوحة المفاتيح إلى إغلاق القائمة، أليس كذلك؟ لنربط هذا الجهاز بالشبكة.
const sidenav = document.querySelector('#sidenav-open');
sidenav.addEventListener('keyup', event => {
if (event.code === 'Escape') document.location.hash = '';
});
سجلّ المتصفح
لمنع التفاعل مع زرَّي الفتح والإغلاق من تجميع عدة إدخالات في سجلّ المتصفّح، أضِف مقتطف JavaScript التالي مضمّنًا في زر الإغلاق:
<a href="#" id="sidenav-close" title="Close Menu" aria-label="Close Menu" onchange="history.go(-1)"></a>
سيؤدي ذلك إلى إزالة إدخال سجلّ عناوين URL عند الإغلاق، ما يجعله يبدو كما لو لم يتم فتح القائمة مطلقًا.
تجربة المستخدم في "التركيز"
يساعدنا المقتطف التالي في التركيز على زرَّي الفتح والإغلاق بعد فتحهما أو إغلاقهما. أريد تسهيل التبديل.
sidenav.addEventListener('transitionend', e => {
const isOpen = document.location.hash === '#sidenav-open';
isOpen
? document.querySelector('#sidenav-close').focus()
: document.querySelector('#sidenav-button').focus();
})
عند فتح شريط التنقّل الجانبي، ركِّز على زر الإغلاق. عند إغلاق شريط التنقّل الجانبي،
ركِّز على زر الفتح. وأُجري ذلك من خلال استدعاء focus()
على العنصر في JavaScript.
الخاتمة
الآن بعد أن عرفت كيف فعلت ذلك، كيف ستفعل ذلك؟ ويؤدي ذلك إلى إنشاء بنية مكونات ممتعة. مَن سينشئ النسخة الأولى التي تتضمّن خانات؟ 🙂
لننوّع الطرق التي نتّبعها ونتعرّف على جميع الطرق لإنشاء تطبيقات على الويب. أنشئ Glitch، ثمّ أرسِل إلينا تغريدة تتضمّن نسختك، وسنضيفها إلى القسم ريمكسات من إنشاء المنتدى أدناه.
الريمكسات التي أنشأها المستخدمون
- @_developit باستخدام عناصر مخصّصة: الإصدار التجريبي والرمز
- @mayeedwin1 باستخدام HTML/CSS/JS: العرض الترويجي والرمز البرمجي
- @a_nurella أنشأت ريمكس Glitch: العرض الترويجي والرمز
- @EvroMalarkey باستخدام HTML/CSS/JS: العرض الترويجي والرمز البرمجي