يعلّمك هذا الدرس التطبيقي كيفية إنشاء مكوّن تخطيط سريع الاستجابة للشريحة الخارجية على الويب. سننشئ المكون مع تقدمنا، بدءًا من HTML، ثم CSS، ثم JavaScript.
يمكنك الاطّلاع على مشاركة مدونتي إنشاء مكوّن Sidenav للتعرّف على ميزات منصة الويب CSS التي تم اختيارها لإنشاء هذا المكوّن.
ضبط إعدادات الجهاز
- انقر على إنشاء ريمكس لتعديل لجعل المشروع قابلاً للتعديل.
- فتح "
app/index.html
"
HTML
أولاً، تعرف على أساسيات إعداد HTML حتى يتوفر محتوى وبعض المربعات للعمل معه.
اسقط رمز HTML التالي في علامة <body>
.
<aside></aside>
<main></main>
يحتوي <aside>
على قائمة التنقّل كعنصر مكمّل لعنصر <main>
الذي يحتوي بدوره على محتوى الصفحة الأساسي.
بعد ذلك، سنملأ هذه العناصر الدلالية بباقي محتوى الصفحة.
أضِف عنصر تنقّل وبعض روابط التنقّل ورابط إغلاق داخل العنصر <aside>
.
<aside>
<nav>
<h4>My</h4>
<a href="#">Dashboard</a>
<a href="#">Profile</a>
<a href="#">Preferences</a>
<a href="#">Archive</a>
<h4>Settings</h4>
<a href="#">Accessibility</a>
<a href="#">Theme</a>
<a href="#">Admin</a>
</nav>
<a href="#"></a>
</aside>
تبدو الروابط رائعة داخل عناصر <nav>
، وتبدو عناصر <nav>
رائعة في الأشرطة الجانبية <aside>
.
لا يزال هناك المزيد من الإجراءات التي يمكننا اتّخاذها لتحسين الأداء.
في عنصر المحتوى الرئيسي، أضف عنوانًا ومقالة للاحتفاظ بمحتوى التنسيق دلاليًا.
<main>
<header>
<a href="#sidenav-open" class="hamburger">
<svg viewBox="0 0 50 40">
<line x1="0" x2="100%" y1="10%" y2="10%" />
<line x1="0" x2="100%" y1="50%" y2="50%" />
<line x1="0" x2="100%" y1="90%" y2="90%" />
</svg>
</a>
<h1>Site Title</h1>
</header>
<article>
{put some placeholder content here}
</article>
</main>
يتضمّن العنوان رابطًا لفتح القائمة. يتضمّن الشريط الجانبي زر الإغلاق. سنعرض العناصر ونخفيها قريبًا استنادًا إلى حجم مساحة العرض.
في عنصر <article>
، لصقنا عبارة نائبة. استبدِل " ``" بمحتوى خاص بك، أو الصِق نص Lorem ipsum المتوفّر أدناه:
<h2>Totam Header</h2>
<p>Lorem ipsum dolor, sit amet consectetur adipisicing elit. Cum consectetur, necessitatibus velit officia ut impedit veritatis temporibus soluta? Totam odit cupiditate facilis nisi sunt hic necessitatibus voluptatem nihil doloribus! Enim.</p>
<p>Lorem ipsum dolor sit, amet consectetur adipisicing elit. Fugit rerum, amet odio explicabo voluptas eos cum libero, ex esse quasi optio incidunt soluta eligendi labore error corrupti! Dolore, cupiditate porro.</p>
<h3>Subhead Totam Odit</h3>
<p>Lorem ipsum dolor sit, amet consectetur adipisicing elit. Fugit rerum, amet odio explicabo voluptas eos cum libero, ex esse quasi optio incidunt soluta eligendi labore error corrupti! Dolore, cupiditate porro.</p>
<p>Lorem ipsum dolor sit, amet consectetur adipisicing elit. Fugit rerum, amet odio explicabo voluptas eos cum libero, ex esse quasi optio incidunt soluta eligendi labore error corrupti! Dolore, cupiditate porro.</p>
<h3>Subhead</h3>
<p>Lorem ipsum dolor sit, amet consectetur adipisicing elit. Fugit rerum, amet odio explicabo voluptas eos cum libero, ex esse quasi optio incidunt soluta eligendi labore error corrupti! Dolore, cupiditate porro.</p>
<p>Lorem ipsum dolor sit, amet consectetur adipisicing elit. Fugit rerum, amet odio explicabo voluptas eos cum libero, ex esse quasi optio incidunt soluta eligendi labore error corrupti! Dolore, cupiditate porro.</p>
وهذا المحتوى وطوله هما ما سيؤديان إلى إمكانية تمرير الصفحة عندما تتجاوز ارتفاع إطار العرض.
لقد أضفت إلى الآن عنصرًا على الجانب يتضمّن شريط تنقّل وروابط وطريقة لإغلاق شريط التنقّل الجانبي. أضفت أيضًا عنوانًا وطريقة لفتح شريط التنقّل الجانبي ومقالة إلى العنصر الرئيسي. هذه العبارة واضحة ودلالية ومناسبة لجميع الأوقات، ولكن يمكننا تحسينها وجعلها أكثر وضوحًا للجميع. يمكن وضع علامة على الرابط المفتوح في شريط التنقّل الجانبي بوضوح أكبر.
أضِف السمتَين title
وaria-label
إلى عنصر الرابط المفتوح في العنوان:
<a href="#sidenav-open" class="hamburger">
<a href="#sidenav-open" title="Open Menu" aria-label="Open Menu" class="hamburger">
يمكن أيضًا وضع علامة على رمز SVG المفتوح بشكل أكثر وضوحًا. أضِف السمات التالية إلى ملف SVG داخل عنصر الرابط المفتوح:
<svg viewBox="0 0 50 40">
<svg viewBox="0 0 50 40" role="presentation" focusable="false" aria-label="trigram for heaven symbol">
يمكن وضع علامة على رابط الإغلاق في شريط التنقّل الجانبي بشكل أكثر وضوحًا.
إضافة السمتين title
وaria-label
إلى عنصر رابط إغلاق التنقل الجانبي:
<a href="#"></a>
<a href="#" title="Close Menu" aria-label="Close Menu"></a>
CSS
حان وقت ترتيب العناصر. إنّ المحتوى الرئيسي
وشريط التنقّل الجانبي هما عنصران ثانويان مباشران للعلامة <body>
، لذا يُعدّ هذان العنصران نقطة بداية جيدة.
أضِف ملف CSS التالي إلى css/sidenav.css
لكي يعرض عنصر <body>
العناصر الفرعية.
body {
display: grid;
grid: [stack] 1fr / min-content [stack] 1fr;
@media (max-width: 540px) {
& > :matches(aside, main) {
grid-area: stack;
}
}
}
يوضّح هذا التنسيق بشكل أساسي ما يلي: أنشئ صفًا مُسمّى stack
يحتوي على كل ما بداخله،
وعمودَين في ذلك الصف، يُطلق على العمود الثاني اسم stack
أيضًا. يجب تحديد حجم العمود الأول
حسب الحد الأدنى لاحتياجات المحتوى، ويمكن أن يشغل العمود الثاني المساحة المتبقية.
بعد ذلك، إذا كان لديك إطار عرض محدود بنسبة 540px
أو أقل، يمكنك وضع عناصر التنقل الجانبي وعناصر المحتوى الرئيسية
في الصف والعمود نفسهما، ليتم عرضهما فوق بعضهما البعض في شبكة 1×1.
باستخدام وظيفة التجميع السريع الاستجابة هذه كأساس، يمكننا الآن الاستفادة من حالة شريط عناوين URL لتبديل مستوى ظهور شريط التنقّل الجانبي ونمط انتقاله.
عدِّل عنصر <aside>
مرة أخرى في app/index.html
:
<aside>
<aside id="sidenav-open">
ويؤدي ذلك إلى تمكين CSS من مطابقة عنصر وتجزئة عنوان URL معًا. هذا مهم لاستخدام :target
.
يمكن الآن لمعرّف العنصر أن يتطابق مع تجزئة عنوان URL التي سنضبطها باستخدام علامات <a>
.
بالإضافة إلى ذلك، لتسهيل استهداف JavaScript، أضِف أرقام تعريف للعناصر الرئيسية التي تتحكّم في شريط التنقّل الجانبي. أولاً، أضِف معرّفًا إلى رابط فتح شريط التنقّل الجانبي:
<a href="#sidenav-open" class="hamburger" title="Open Menu" aria-label="Open Menu">
<a href="#sidenav-open" id="sidenav-button" class="hamburger" title="Open Menu" aria-label="Open Menu">
بعد ذلك، أضِف معرّفًا إلى رابط إغلاق شريط التنقّل الجانبي:
<a href="#" title="Close Menu" aria-label="Close Menu"></a>
<a href="#" id="sidenav-close" title="Close Menu" aria-label="Close Menu"></a>
يُختتم هذا القسم بعرض تخطيط التجميع السريع الاستجابة للوحدة الماكرو <body>
، بالإضافة إلى ربطنا بشريط عناوين URL.
لنواصل التقدم!
يتميز <aside>
بتصميم أنيق أيضًا. ويتضمّن عنصرَين ثانويَين، <nav>
وهو مكوّن يشبه الورق ينبثق للخارج، وعنصر رابط <a>
للإغلاق يضبط عنوان URL على #
.
يكون الرابط غير مرئي على يمين تنقل الورق، وذلك حتى يتمكن الأشخاص من "النقر فوق" المكون المرئي لإزالته.
أضِف مقتطف CSS التالي إلى css/sidenav.css
:
#sidenav-open {
display: grid;
grid-template-columns: [nav] 2fr [escape] 1fr;
}
اعتقدت أن النسبة والأسماء كانت لمسة لطيفة حقًا هنا، حيث يمكن أن تتألق الشبكة وتعطي المصمم الكثير من التحكم.
بعد ذلك، أحتاج إلى تراكب المحتوى الرئيسي بشكل مشروط والحفاظ
على موضعي من خلال أي تمرير للمستند. هذه وظيفة رائعة لـ position: sticky
و
بعض overscroll-behavior
.
أضِف الأنماط التالية إلى شريط التنقّل الجانبي:
#sidenav-open {
display: grid;
grid-template-columns: [nav] 2fr [escape] 1fr;
@media (max-width: 540px) {
position: sticky;
top: 0;
max-height: 100vh;
overflow: hidden auto;
overscroll-behavior: contain;
visibility: hidden; /* not keyboard accessible when closed */
}
}
تضمن هذه الأنماط أن يكون ارتفاع شريط التنقّل الجانبي هو ارتفاع إطار العرض، وأن يتم التمرير عموديًا
ويحتوي على شريط التمرير. والأهم من ذلك أنه يخفي العنصر. بشكلٍ تلقائي،
يتم إخفاء شريط التنقّل الجانبي هذا عندما يكون إطار العرض 540px
أو أصغر. ما لم يكن
أضِف أداة اختيار وهمية :target
إلى العنصر #sidenav-open
:
#sidenav-open {
@media (max-width: 540px) {
&:target {
visibility: visible;
}
}
}
عندما يكون رقم تعريف هذا العنصر وشريط عناوين URL متطابقَين،
اضبط visibility
على visible
. يمكنك فتح القائمة الجانبية بعد الانتقال إلى أسفل الصفحة،
أو محاولة الانتقال إلى أسفل الصفحة عندما تكون القائمة الجانبية مفتوحة. ما رأيك؟
أضِف ملف CSS التالي إلى أسفل app/sidenav.css
:
#sidenav-button,
#sidenav-close {
-webkit-tap-highlight-color: transparent;
-webkit-touch-callout: none;
user-select: none;
touch-action: manipulation;
@media (min-width: 540px) {
display: none;
}
}
تستهدف هذه الأنماط أزرار الفتح والإغلاق، وتحدّد أنماط النقر واللمس الخاصة بها،
وتخفيها أيضًا عندما تكون مساحات العرض 540px
أو أكبر.
لإضافة بعض لمسة مميزة، يمكننا إضافة تحويلات CSS مع توفير إمكانية الوصول المحترمة.
أضِف مقتطف CSS التالي إلى css/sidenav.css
:
#sidenav-open {
--easeOutExpo: cubic-bezier(0.16, 1, 0.3, 1);
--duration: .6s;
...
@media (max-width: 540px) {
...
transform: translateX(-110vw);
will-change: transform;
transition:
transform var(--duration) var(--easeOutExpo),
visibility 0s linear var(--duration);
&:target {
visibility: visible;
transform: translateX(0);
transition: transform var(--duration) var(--easeOutExpo);
}
}
@media (prefers-reduced-motion: reduce) {
--duration: 1ms;
}
}
إضافة بعض JavaScript
من المفترض أن يؤدي الضغط على مفتاح Escape
إلى إغلاق القائمة. إضافة ملف JavaScript هذا إلى js/index.js
:
const sidenav = document.querySelector('#sidenav-open');
sidenav.addEventListener('keyup', e => {
if (e.code === 'Escape') {
document.location.hash = '';
}
});
ويرصد هذا الحدث حدثًا رئيسيًا في عنصر التنقل الجانبي.
أما إذا كانت القيمة Escape
، فهي تضبط تجزئة عنوان URL على فارغة، ما يؤدي إلى الانتقال الجانبي للخارج.
هذه القطعة التالية من UX JS هي إدارة التركيز. أريد تسهيل عملية الفتح والإغلاق، لذلك أنتظر إلى أن ينتهي شريط التنقّل الجانبي من عملية انتقال من نوع ما، ثم أتحقّق منه مقارنةً بملف هَشٍ لعنوان URL لتحديد ما إذا كان مفتوحًا أو مغلقًا. بعد ذلك، أستخدِم JavaScript لضبط التركيز على الزر المكمل للزر الذي ضغط عليه المستخدم للتو.
أضِف رمز JavaScript التالي إلى js/index.js
:
const closenav = document.querySelector('#sidenav-close');
const opennav = document.querySelector('#sidenav-button');
sidenav.addEventListener('transitionend', e => {
if (e.propertyName !== 'transform') {
return;
}
const isOpen = document.location.hash === '#sidenav-open';
isOpen
? closenav.focus()
: opennav.focus();
});
جرّبه الآن
- لمعاينة الموقع الإلكتروني، اضغط على عرض التطبيق، ثم اضغط على ملء الشاشة .
الخاتمة
هذه هي المتطلّبات التي كانت لديّ بشأن المكوّن. يمكنك استخدام هذه العناصر، أو بدء العمل عليها باستخدام حالة JavaScript بدلاً من عنوان URL، وجعلها مناسبة لك بشكل عام. هناك دائمًا المزيد من المعلومات التي يمكن إضافتها أو المزيد من حالات الاستخدام التي يمكن تغطيتها.
افتح css/brandnav.css
للاطّلاع على الأنماط غير المرتبطة بالتنسيق التي طبّقتها على
هذا المكوّن. لم أشعر أنه من المهم لمجموعة الميزات التي كنت أركز عليها،
وأتمنى أن يؤدي فصل الأنماط عن التخطيط إلى تشجيع النسخ واللصق. يمكن أن يكون هناك
المزيد من التعلم لك هناك!
كيف يمكنك إنشاء مكونات قائمة جانبية سريعة الاستجابة للانزلاق للخارج؟ هل لديك أي وقت مضى أكثر من 1، مثل واحد على كلا الجانبين؟ يسرّني عرض الحلّ الذي وجدته في فيديو على YouTube. يُرجى مراسلتي على Twitter أو نشر تعليق على YouTube يتضمّن الرمز، ما سيساعد الجميع في حلّ المشكلة.