نظرة عامة أساسية حول كيفية إنشاء انزلاق سريع الاستجابة خارج التنقل الجانبي
أود أن أشارككم في هذه المشاركة كيف صممتُ نموذجًا أوّليًا لمكون Sidenav للويب سريع الاستجابة ومميز ويتوافق مع التنقل بلوحة المفاتيح ويعمل مع JavaScript وبدونه وتعمل عبر المتصفحات. جرِّب العرض التوضيحي.
إليك نسخة من هذه المشاركة على YouTube إذا كنت تفضّل ذلك:
نظرة عامة
من الصعب إنشاء نظام تنقل سريع الاستجابة. سيكون بعض المستخدمين على لوحة مفاتيح، فبعضها لديه أجهزة كمبيوتر مكتبية قوية، بينما يزور البعض الآخر من جهاز محمول صغير. من المفترض أن يتمكّن جميع الزوّار من فتح القائمة وإغلاقها.
أساليب الويب
في هذا استكشاف المكونات، استمتعتُ بالجمع بين بعض الميزات المهمة لمنصات الويب:
- خدمة مقارنة الأسعار (CSS)
:target
- شبكة CSS
- عمليات تحويل CSS
- طلبات بحث وسائط CSS لإطار العرض والإعدادات المفضّلة للمستخدم
- رمز 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، باستخدام بنية 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
كي لا يدخل تركيز لوحة المفاتيح إلى العنصر خارج الشاشة.
عندما أبدأ في تنفيذ الرسوم المتحركة للحركة، أريد أن أبدأ بإمكانية الوصول في مقدمة أولوياتي.
حركة يسهل الوصول إليها
لن يرغب الجميع في تجربة حركة التمرير. في حلنا هذا التفضيل
عن طريق ضبط متغيّر CSS --duration
داخل استعلام عن الوسائط. تمثل قيمة الاستعلام عن الوسائط هذه
تفضيل نظام تشغيل المستخدم للحركة (إن وجد).
#sidenav-open {
--duration: .6s;
}
@media (prefers-reduced-motion: reduce) {
#sidenav-open {
--duration: 1ms;
}
}
والآن عندما ينزلق التنقل الجانبي للفتح والإغلاق، وإذا كان المستخدم يفضل الحركة الأقل، أقوم بتحريك العنصر على الفور إلى العرض، مع الحفاظ على حالته بدون حركة.
التحوّل أو التحويل أو الترجمة
Sidenav out (تلقائي)
لضبط الحالة التلقائية للتنقّل الجانبي على الأجهزة الجوّالة على وضع خارج الشاشة،
أُحدِّد موضع العنصر في 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 في
عندما يتطابق العنصر #sidenav
مع القيمة :target
، اضبط موضع translateX()
على القاعدة الرئيسية 0
،
ومشاهدة CSS وهي تسحب العنصر من موضعه الخارجي -110vw
إلى "in"
الموضع 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.
الخاتمة
والآن بعد أن عرفت كيف فعلت ذلك، كيف حالك؟! هذا يجعل بعض البنية الممتعة للمكونات! من سينشئ الإصدار الأول الذي يتضمّن خانات؟ 🙂
هيا ننوي تنويع وتعلم جميع طرق الإنشاء على الويب. أنشئ خللاً، تغريدة نسختك، وسأضيفها إلى قسم الريمكسات في المنتدى أدناه
ريمكسات من إنشاء المنتدى
- @_developit مع عناصر مخصّصة: demo & الرمز
- @mayeedwin1 مع HTML/CSS/JS: demo & الرمز
- @a_nurella مع ريمكس لتطبيق Glitch: demo & الرمز
- @EvroMalarkey مع HTML/CSS/JS: demo & الرمز