إنشاء مكوّن علامات التبويب

نظرة عامة أساسية حول كيفية إنشاء مكوِّن علامات تبويب مشابه لتلك الموجودة في تطبيقات iOS وAndroid.

أود أن أشارككم في هذه المشاركة بعض الأفكار المتعلقة بإنشاء مكوّن علامات التبويب على الويب سريع الاستجابة، ويمكن إدخال عدة إدخالات للأجهزة، ويعمل عبر المتصفحات. جرِّب العرض التوضيحي.

عرض توضيحي

إليك نسخة من هذه المشاركة على YouTube إذا كنت تفضّل ذلك:

نظرة عامة

تعد علامات التبويب عنصرًا شائعًا في أنظمة التصميم ولكن يمكن أن تتخذ العديد من الأشكال النماذج. في البداية، كانت هناك علامات تبويب لسطح المكتب مبنية على العنصر <frame>، والآن مكونات الأجهزة الجوّالة الزبدية التي تحرّك المحتوى بناءً على الخصائص الفيزيائية. يحاولون جميعًا تنفيذ الشيء نفسه: توفير مساحة.

اليوم، أساسيات تجربة مستخدم علامات التبويب هي منطقة التنقل للأزرار الذي يعمل على إيقاف إمكانية رؤية المحتوى في إطار العرض. العديد من الأنواع المختلفة تشترك مناطق المحتوى في نفس المساحة، ولكن يتم تقديمها بشكل مشروط استنادًا إلى المحدد في شريط التنقل.

تصبح الصورة المجمعة فوضوية تمامًا بسبب التنوع الكبير في الأنماط التي طبقها الويب على مفهوم المكون
صورة مجمّعة لأنماط تصميم الويب لمكوّنات علامة التبويب من آخر 10 سنوات

أساليب الويب

وبشكل عام، وجدت هذا المكون أمرًا سهلاً للغاية في الإنشاء، وذلك بفضل بعض الميزات المهمة لمنصة الويب وهي:

  • scroll-snap-points لتمرير سريع وتفاعلات لوحة المفاتيح بشكل أنيق مع مواضع إيقاف التمرير المناسبة
  • روابط لصفحات في التطبيق عبر تجزئات عناوين URL لعنوان URL دعم خاصية إرساء التنقل والمشاركة في الصفحة لمعالجة المتصفّح
  • إتاحة قارئ الشاشة مع ترميز العنصرين <a> وid="#hash"
  • prefers-reduced-motion لتفعيل انتقالات التلاشي المتقاطع والفوري التنقّل في الصفحة
  • ميزة الويب "@scroll-timeline" المضمّنة في مسودة ميزة "التسطير الديناميكي" تغيير لون علامة التبويب المحدَّدة

لغة HTML

وفي الأساس، تكون تجربة المستخدم هنا: النقر على رابط، وجعل عنوان URL يمثل العنوان المضمن جديدة، ثم سيظهر لك تحديث منطقة المحتوى أثناء انتقال المتصفح إلى .

ويتضمّن المحتوى الهيكلي بعض العناصر، مثل الروابط و:target. أر بحاجة إلى قائمة بالروابط، حيث يمكن استخدام <nav>، وقائمة بـ <article> من العناصر، والتي يكون <section> رائعًا لها. ستتطابق كل تجزئة رابط مع قسم، مما يتيح للمتصفح تمرير الأشياء عبر الإرساء.

يتم النقر على زر رابط، ويتم الانتقال إلى المحتوى الذي يتم التركيز عليه.

على سبيل المثال، يؤدي النقر على رابط إلى تركيز المقالة :target تلقائيًا في الإصدار 89 من Chrome، بدون الحاجة إلى JavaScript. يمكن للمستخدم بعد ذلك تمرير محتوى المقالة باستخدام جهاز الإدخال الخاص بهم كما هو الحال دائمًا. وهو محتوى مجاني، كما هو موضح في الترميز.

استخدمت الترميز التالي لتنظيم علامات التبويب:

<snap-tabs>
  <header>
    <nav>
      <a></a>
      <a></a>
      <a></a>
      <a></a>
    </nav>
  </header>
  <section>
    <article></article>
    <article></article>
    <article></article>
    <article></article>
  </section>
</snap-tabs>

يمكنني إنشاء اتصالات بين العناصر <a> و<article> باستخدام سمات href وid المشابهة لما يلي:

<snap-tabs>
  <header>
    <nav>
      <a href="#responsive"></a>
      <a href="#accessible"></a>
      <a href="#overscroll"></a>
      <a href="#more"></a>
    </nav>
  </header>
  <section>
    <article id="responsive"></article>
    <article id="accessible"></article>
    <article id="overscroll"></article>
    <article id="more"></article>
  </section>
</snap-tabs>

ثم ملأت المقالات بكميات مختلطة من lorem، والروابط مجموعة من العناوين والصور المختلفة ومع المحتوى الذي سنتعامل معه، يمكننا بدء التصميم.

تنسيقات التمرير

هناك 3 أنواع مختلفة من مناطق التمرير في هذا المكوِّن:

  • شريط التنقُّل (الوردي) أفقيًا قابل للتمرير
  • تكون منطقة المحتوى (blue) أفقيًا. قابل للتمرير
  • يكون كل عنصر مقالة (أخضر) عموديًا قابل للتمرير.
3 مربعات ملونة مع أسهم اتجاهية مطابقة للألوان تحدد مناطق الانتقال للأسفل/للأعلى وتوضّح الاتجاه الذي سيتم الانتقال فيه إلى الأسفل

هناك نوعان مختلفان من العناصر المرتبطة بالتمرير:

  1. نافذة
    مربّع بأبعاد محدّدة تحتوي على overflow نمط الملكية.
  2. سطح كبير
    في هذا التنسيق، تكون حاويات القائمة هي: التنقل والروابط ومقالات القسم ومحتويات المقالة.

التنسيق <snap-tabs>

كان تخطيط المستوى الأعلى الذي اخترته مرنًا (Flexbox). قمتُ بتعيين الاتجاه إلى column، لذلك يتم ترتيب العنوان والقسم عموديًا. هذا هو أول نافذة التمرير، ويتم إخفاء كل شيء مع إخفاء تجاوز. العنوان التمرير الزائد قريبًا، كمناطق فردية.

HTML
<snap-tabs>
  <header></header>
  <section></section>
</snap-tabs>
CSS
  snap-tabs {
  display: flex;
  flex-direction: column;

  /* establish primary containing box */
  overflow: hidden;
  position: relative;

  & > section {
    /* be pushy about consuming all space */
    block-size: 100%;
  }

  & > header {
    /* defend against 
needing 100% */ flex-shrink: 0; /* fixes cross browser quarks */ min-block-size: fit-content; } }

الإشارة مرة أخرى إلى الرسم التخطيطي الملون ثلاثي التمرير:

  • أصبح تطبيق "<header>" جاهزًا الآن ليصبح (باللون الوردي) حاوية التمرير.
  • تم إعداد <section> ليكون شريط التمرير (أزرق) .

الإطارات التي قمت بتمييزها أدناه باستخدام يساعدنا VisBug في رؤية نوافذ تم إنشاء حاويات التمرير.

يحتوي عناصر العنوان والقسم على تراكبات لونية ساخنة، تحدد المساحة التي تشغلها في المكوِّن

تنسيق <header> لعلامات التبويب

التنسيق التالي هو نفسه تقريبًا: أستخدم المرونة لإنشاء ترتيب رأسي.

HTML
<snap-tabs>
  <header>
    <nav></nav>
    <span class="snap-indicator"></span>
  </header>
  <section></section>
</snap-tabs>
CSS
header {
  display: flex;
  flex-direction: column;
}

يجب أن تسافر .snap-indicator أفقيًا مع مجموعة الروابط يساعد تخطيط العنوان هذا في إعداد هذه المرحلة. ما مِن عناصر في مواضع مطلقة هنا!

يحتوي عنصرا nav وspan.indicator على تراكبات لونية ساخنة بها، تحدد المساحة التي تشغلها في المكون

بعد ذلك، أنماط التمرير. اتضح أنه يمكننا مشاركة أنماط التمرير بين منطقتي التمرير الأفقيتين (العنوان والقسم)، لذلك أنشأت أداة الصف، .scroll-snap-x.

.scroll-snap-x {
  /* browser decide if x is ok to scroll and show bars on, y hidden */
  overflow: auto hidden;
  /* prevent scroll chaining on x scroll */
  overscroll-behavior-x: contain;
  /* scrolling should snap children on x */
  scroll-snap-type: x mandatory;

  @media (hover: none) {
    scrollbar-width: none;

    &::-webkit-scrollbar {
      width: 0;
      height: 0;
    }
  }
}

يحتاج كل منها إلى تجاوز حدود المحور "س"، وتمرير الاحتواء، ليتم حجب التمرير الزائد، مخفي. أشرطة تمرير للأجهزة التي تعمل باللمس، وأخيرًا محاذاة أشرطة التمرير لقفل المحتوى مجالات العرض التقديمي. يمكن الوصول إلى ترتيب علامات تبويب لوحة المفاتيح وأي دليل تفاعلات التركيز بشكل طبيعي. تحصل حاويات التمرير على شكل لوحة عرض دوّارة رائعة أيضًا التفاعل من لوحة المفاتيح.

تنسيق عنوان علامات التبويب <nav>

يجب وضع روابط التنقل في سطر بدون فواصل أسطر، عموديًا في الوسط، ويجب محاذاة كل عنصر رابط إلى حاوية محاذاة التمرير. Swift تناسب منصة CSS لعام 2021

HTML
<nav>
  <a></a>
  <a></a>
  <a></a>
  <a></a>
</nav>
CSS
  nav {
  display: flex;

  & a {
    scroll-snap-align: start;

    display: inline-flex;
    align-items: center;
    white-space: nowrap;
  }
}

كل نمط وأحجام للرابط نفسه، لذلك يحتاج تخطيط التنقل فقط إلى تحديد الاتجاه والتدفق. يؤدي استخدام عرض فريد لعناصر التنقل إلى الانتقال بين علامات التبويب مرحًا حيث يقوم المؤشر بضبط عرضه بحيث يتوافق مع الهدف الجديد. بناءً على عدد الموجودة هنا، سيعرض المتصفح شريط تمرير أو لا.

احتواء عناصر التنقل على تراكبات لون الوردي، تحدد المساحة التي تشغلها في المكون بالإضافة إلى المكان الذي تفرغ منه

تنسيق <section> لعلامات التبويب

هذا القسم هو عنصر مرن ويجب أن يكون المستهلك الرئيسي للمساحة. أُنشأها جون هنتر، الذي كان متخصصًا أيضًا إنشاء أعمدة لوضع المقالات فيها. مرة أخرى، بسرعة تتوافق مع CSS 2021 يوسع block-size: 100% هذا العنصر لملء الأصلية قدر الإمكان، ثم تنشئ لتخطيطها سلسلة من التي تكون 100% بعرض الوحدة الرئيسية. النسب المئوية مناسبة هنا لأننا كتبنا قيودًا قوية على الأصل.

HTML
<section>
  <article></article>
  <article></article>
  <article></article>
  <article></article>
</section>
CSS
  section {
  block-size: 100%;

  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 100%;
}

يبدو الأمر كما لو أننا نقول "التوسع عموديًا قدر الإمكان، وبطريقة حاسمة" (تذكّر العنوان الذي تم ضبطه على flex-shrink: 0: للدفاع عن ذلك دفع توسيع)، الذي يضبط ارتفاع الصف لمجموعة من الأعمدة ذات الارتفاع الكامل. تشير رسالة الأشكال البيانية يوجِّه نمط auto-flow الشبكة إلى وضع الأطفال في وضع أفقي دائمًا ولا يوجد التفاف، فهذا ما نريده بالضبط؛ تجاوز النافذة الرئيسية.

احتواء عناصر المقالة على طبقات وردية ساخنة تحدّد فيها المساحة التي تشغلها في المكوِّن والمكان الذي تفرغ منه

أجد ذلك صعبًا في بعض الأحيان! عنصر القسم هذا يلائم الصندوق، بل يصنع أيضًا مجموعة من الصناديق. آمل أن تكون العناصر المرئية التفسيرات مفيدة.

تنسيق <article> لعلامات التبويب

يجب أن يتمكن المستخدم من تمرير محتوى المقالة، ويجب أن تكون أشرطة التمرير إلا إذا كان هناك تجاوز. عناصر المقالة هذه مرتبة الموقع. وهما في الوقت نفسه عنصر رئيسي للتمرير وعنصر ثانوي بالتمرير. تشير رسالة الأشكال البيانية يتعامل المتصفّح مع بعض تفاعلات اللمس والماوس ولوحة المفاتيح الصعبة لنا هنا.

HTML
<article>
  <h2></h2>
  <p></p>
  <p></p>
  <h2></h2>
  <p></p>
  <p></p>
  ...
</article>
CSS
article {
  scroll-snap-align: start;

  overflow-y: auto;
  overscroll-behavior-y: contain;
}

اخترتُ أن تكون المقالات سريعة داخل أشرطة التمرير الرئيسية. أنا حقًا أحب كيفية محاذاة عناصر رابط التنقل وعناصر المقالة إلى بداية الصفحة من حاويات التمرير الخاصة بها. يبدو وكأنه متناغم العلاقة.

يحتوي عنصر المقالة وعناصره الفرعية على تراكبات وردية سريعة، تحدّد المساحة التي تشغلها في المكوِّن والاتجاه الذي تفرغ منه

تعرض المقالة عنصرًا فرعيًا من الشبكة، ويتم تحديد حجمها مسبقًا ليكون إطار العرض. المجال الذي نريد توفير تجربة المستخدم التمرير فيه. هذا يعني أنّني لست بحاجة إلى أي ارتفاع أو عرض. الأنماط هنا، فأنا بحاجة فقط إلى تحديد كيفية تجاوزه. قمت بتعيين overflow-y على "auto"، ثم استهداف تفاعلات التمرير من خلال السلوك السهل للتمرير الزائد الموقع.

ملخص 3 مناطق التمرير

أدناه، اخترت "عرض أشرطة التمرير دائمًا" في إعدادات النظام. أعتقد من المهم للغاية أن يعمل التخطيط مع تشغيل هذا الإعداد، حيث بالنسبة لي لمراجعة التخطيط وتنسيق التمرير.

تم تعيين أشرطة التمرير الثلاثة للعرض، وتستهلك الآن مساحة التخطيط، ولا يزال المكون يبدو رائعًا

أعتقد أن رؤية هامش توثيق شريط التمرير في هذا المكون يساعد في إظهار مكان مناطق التمرير والاتجاه الذي تدعمه وكيفية تفاعلها مع بعضنا البعض. ضع في اعتبارك كيف أن كل من إطارات نافذة التمرير هذه مرن أو العناصر الرئيسية للشبكة إلى تخطيط.

يمكن أن تساعدنا أدوات مطوري البرامج في تصور ما يلي:

تحتوي مناطق التمرير على تراكبات على شكل مربّعات وأداة flexbox، تحدد المساحة التي تشغلها في المكون والاتجاه الذي تتجاوزه
أدوات مطوري البرامج في Chromium تعرض تنسيق عنصر التنقل flexbox المليء بعناصر الارتساء، تخطيط قسم الشبكة المليء بعناصر المقالة، والمقالة وعناصر مليئة بالفقرات وعنصر العنوان.

تخطيطات التمرير كاملة: الانطباق والربط بعمق ولوحة المفاتيح إليه على الفور. أساس قوي لتحسين تجربة المستخدم والأسلوب والبهجة.

تسليط الضوء على الميزات

ويحافظ الأطفال الذين تم نقلهم على الشاشة أثناء التمرير على وضع قفلهم أثناء تغيير الحجم. يعني ذلك لن تحتاج لغة JavaScript إلى عرض أي محتوى على ميزة تدوير الجهاز أو المتصفح لتغيير الحجم. يمكنك تجربته على جهاز أدوات مطوري البرامج في Chromium. الوضع من قِبل واختيار أي وضع غير متجاوب، ثم تغيير حجم إطار الجهاز. لاحِظ أنّ العنصر يظل معروضًا ومقفلاً باستخدام محتواه. كان هذا متاحة لأن Chromium حدّث تنفيذها ليتطابق مع المواصفات. إليك مشاركة مدونة حول هذا الموضوع.

Animation

الهدف من عمل الرسوم المتحركة هنا هو ربط التفاعلات بوضوح مع واجهة المستخدم الملاحظات. يساعد هذا في توجيه المستخدم أو مساعدته خلال سهولة اكتشاف كل المحتوى. سأضيف حركة بهدف بشروط. يمكن للمستخدمين الآن تحديد حركتهم والتفضيلات في نظام التشغيل لديهم، وأستمتع تمامًا بالرد على تفضيلاتهم في واجهاتي.

سأربط تسطير علامة التبويب بموضع تمرير المقالة. المحاذاة ليس كذلك محاذاة جميلة فقط، بل يتم أيضًا إرساء بداية ونهاية الرسوم المتحركة. يحافظ هذا على <nav>، الذي يعمل كـ خريطة مصغّرة مرتبطة بالمحتوى. سنتحقق من تفضيل حركة المستخدم من كل من CSS وJS. تتوفر بعض الأماكن الرائعة التي يجب أخذها في الاعتبار!

سلوك التمرير

هناك فرصة لتحسين سلوك الحركة لكل من :target و element.scrollIntoView() وبشكل افتراضي، يكون التطبيق فوريًا. يضبط المتصفح واجهة موضع التمرير. حسنًا، ماذا لو أردنا الانتقال إلى موضع التمرير هذا، بدلاً من الوميض

@media (prefers-reduced-motion: no-preference) {
  .scroll-snap-x {
    scroll-behavior: smooth;
  }
}

نظرًا لأننا نقدم الحركة هنا، والحركة التي لا يتحكم فيها المستخدم (مثل التمرير)، لا نطبق هذا النمط إلا إذا لم يكن لدى المستخدم تفضيل في نظام التشغيل حول الحركة المخفضة. بهذه الطريقة، نقدم فقط التمرير والحركة للأشخاص الذين يوافقون عليها.

مؤشر علامات التبويب

الغرض من هذه الرسوم المتحركة هو المساعدة في ربط المؤشر بالحالة من المحتوى. قرّرتُ استخدام تلاشٍ متقاطع لأنماط border-bottom للمستخدمين الذين يفضلون الحركة المخفضة، والرسوم المتحركة بالتمرير المرتبط بالتمرير + تلاشي اللون للمستخدمين الذين يوافقون على الحركة.

في Chromium Devtools، يمكنني تبديل التفضيل وتوضيح أنماط انتقال مختلفة. لقد استمتعت كثيرًا ببناء هذا.

@media (prefers-reduced-motion: reduce) {
  snap-tabs > header a {
    border-block-end: var(--indicator-size) solid hsl(var(--accent) / 0%);
    transition: color .7s ease, border-color .5s ease;

    &:is(:target,:active,[active]) {
      color: var(--text-active-color);
      border-block-end-color: hsl(var(--accent));
    }
  }

  snap-tabs .snap-indicator {
    visibility: hidden;
  }
}

أخفي ".snap-indicator" عندما يفضّل المستخدم الحركة المخفّضة لأنّني لا أفضّلها الاحتياج إليه بعد الآن. بعد ذلك، استبدلها بأنماط border-block-end transition لاحظ أيضًا في تفاعل علامات التبويب أن عنصر التنقل النشط لا بها تمييز تسطير علامة تجارية فقط، لكن لون نصها أغمق أيضًا. تشير رسالة الأشكال البيانية العنصر النشط بتباين ألوان أعلى وتمييز ساطع تحت الإضاءة.

فقط بضعة أسطر إضافية من CSS ستجعل الشخص يشعر بأن فإننا نحترم تفضيلات الحركة لديه بعناية). أحب ذلك.

@scroll-timeline

في القسم أعلاه، أوضحتُ لك كيفية التعامل مع التلاشي المتقاطع للحركة المخفّضة. والأنماط، وفي هذا القسم سأوضح لك كيف قمت بربط المؤشر منطقة التمرير معًا. إليك بعض الأشياء التجريبية الممتعة التالية. أتمنى أن تكون متحمسًا مثلي.

const { matches:motionOK } = window.matchMedia(
  '(prefers-reduced-motion: no-preference)'
);

أتحقق أولاً من تفضيل حركة المستخدم من JavaScript. إذا كانت نتيجة هذه false، أي أنّ المستخدم يفضّل الحركة المخفّضة، لذا لن ننفّذ لتأثيرات حركة ربط التمرير.

if (motionOK) {
  // motion based animation code
}

في وقت كتابة هذه الرسالة، كان دعم المتصفح @scroll-timeline ما مِن قيمة. إنها مسودة المواصفات تشتمل فقط وعمليات التنفيذ التجريبية. إنه يحتوي على رمز polyfill، والتي أستخدمها في هذه تجريبي.

ScrollTimeline

بينما يمكن لكل من CSS وJavaScript إنشاء مخططات زمنية للتمرير، فقد اشتركت JavaScript حتى أتمكن من استخدام قياسات العناصر المباشرة في الرسوم المتحركة.

const sectionScrollTimeline = new ScrollTimeline({
  scrollSource: tabsection,  // snap-tabs > section
  orientation: 'inline',     // scroll in the direction letters flow
  fill: 'both',              // bi-directional linking
});

أريد أن يتبع شيء واحد موضع التمرير الخاص بشيء آخر، ومن خلال إنشاء ScrollTimeline أحدِّد مشغّل رابط التمرير، scrollSource. عادةً ما تعمل الصورة المتحركة على الويب مع علامة الإطار الزمني العالمي، ولكن مع sectionScrollTimeline مخصص في الذاكرة، يمكنني تغيير كل ذلك.

tabindicator.animate({
    transform: ...,
    width: ...,
  }, {
    duration: 1000,
    fill: 'both',
    timeline: sectionScrollTimeline,
  }
);

قبل أن أدخل في الإطارات الرئيسية للرسوم المتحركة، أعتقد أنه من المهم للإشارة إلى أنّ متابع التمرير، tabindicator، سيكون استنادًا إلى صورة متحركة في المخطط الزمني المخصص، تمرير القسم. هذا يكمل الارتباط، ولكنه يفتقد إلى المكون النهائي، ونقاط محددة للحركة بينهما، والمعروفة أيضًا باسم والإطارات الرئيسية.

الإطارات الرئيسية الديناميكية

تتوفر أيضًا طريقة CSS واضحة جدًا لإضافة تأثيرات حركية إلى المحتوى @scroll-timeline، ولكن الصورة المتحركة التي اخترتُ تنفيذها كانت ديناميكية جدًا. لا توجد للانتقال بين عرض auto، وليست هناك طريقة لإنشاء عدد من الإطارات الرئيسية استنادًا إلى طول الأطفال.

على الرغم من ذلك، تعرف JavaScript كيفية الحصول على هذه المعلومات، لذلك سنكررها على الأطفال بأنفسنا ونحصل على القيم المحسوبة في وقت التشغيل:

tabindicator.animate({
    transform: [...tabnavitems].map(({offsetLeft}) =>
      `translateX(${offsetLeft}px)`),
    width: [...tabnavitems].map(({offsetWidth}) =>
      `${offsetWidth}px`)
  }, {
    duration: 1000,
    fill: 'both',
    timeline: sectionScrollTimeline,
  }
);

عليك إتلاف موضع offsetLeft في كل tabnavitem وعرض سلسلة. التي تستخدمها كقيمة translateX. يعمل هذا على إنشاء 4 إطارات رئيسية قابلة للتحويل الرسوم المتحركة. وينطبق الأمر نفسه على العرض، ويُطلب من كل منهم معرفة عرضه الديناميكي ثم يتم استخدامها كقيمة للإطار الرئيسي.

في ما يلي مثال على الإخراج، استنادًا إلى الخطوط والإعدادات المفضّلة للمتصفح:

الإطارات الرئيسية في TranslateX:

[...tabnavitems].map(({offsetLeft}) =>
  `translateX(${offsetLeft}px)`)

// results in 4 array items, which represent 4 keyframe states
// ["translateX(0px)", "translateX(121px)", "translateX(238px)", "translateX(464px)"]

عرض الإطارات الرئيسية:

[...tabnavitems].map(({offsetWidth}) =>
  `${offsetWidth}px`)

// results in 4 array items, which represent 4 keyframe states
// ["121px", "117px", "226px", "67px"]

لتلخيص الاستراتيجية، سيتم تحريك مؤشر التبويب (Tab) الآن في 4 إطارات رئيسية. بناءً على موضع محاذاة التمرير في شريط تمرير القسم. نقاط الانطباق إنشاء تحديد واضح بين الإطارات الرئيسية وإضافة وشعورًا متناسقًا مع الرسوم المتحركة.

علامة التبويب النشطة وعلامة التبويب غير النشِطة تظهر مع تراكبات VisBug التي تُظهر درجات التباين التي تم اجتيازها لكليهما

يقود المستخدم الرسوم المتحركة بتفاعله، ورؤية العرض يتغير موضع المؤشر من قسم إلى آخر، بشكل مثالي باستخدام التمرير.

ربما لم تكن قد لاحظت ذلك، لكني فخور جدًا بانتقال اللون مثل عنصر التنقل المميز.

يظهر اللون الرمادي الفاتح الذي لم يتم تحديده بشكل رديء أكثر عند تمييز العنصر به مزيد من التباين. من الشائع تبديل اللون للنص، مثل التمرير عند التمرير. وعند تحديده، يتم نقل هذا اللون عند التمرير في المستوى التالي، متزامنًا مع مؤشر التسطير.

إليك كيفية إجراء ذلك:

tabnavitems.forEach(navitem => {
  navitem.animate({
      color: [...tabnavitems].map(item =>
        item === navitem
          ? `var(--text-active-color)`
          : `var(--text-color)`)
    }, {
      duration: 1000,
      fill: 'both',
      timeline: sectionScrollTimeline,
    }
  );
});

يحتاج كل رابط تنقُّل في علامة التبويب إلى هذه الصورة المتحركة الملونة الجديدة، والتي تتتبّع التمرير نفسه. المخطط الزمني كمؤشر تسطير. أستخدم نفس الجدول الزمني كما كان من قبل: نظرًا يتمثل دورها في وضع علامة عند التمرير، يمكننا استخدام هذه العلامة في أي نوع من والرسوم المتحركة التي نريدها. كما فعلت من قبل، أقوم بإنشاء 4 إطارات رئيسية في التكرار الحلقي، وأرجع الألوان.

[...tabnavitems].map(item =>
  item === navitem
    ? `var(--text-active-color)`
    : `var(--text-color)`)

// results in 4 array items, which represent 4 keyframe states
// [
  "var(--text-active-color)",
  "var(--text-color)",
  "var(--text-color)",
  "var(--text-color)",
]

إنّ الإطار الرئيسي الذي يحمل اللون var(--text-active-color) يميّز الرابط يكون لون نص قياسي بخلاف ذلك. التكرار الحلقي المتداخل يجعل من مباشرة، حيث إن التكرار الحلقي الخارجي هي كل عنصر تنقل، والحلقة الداخلية عبارة عن الإطارات الرئيسية الشخصية لـ navitem. أتحقق مما إذا كان عنصر التكرار الخارجي مماثلاً حلقة التكرار الداخلي، واستخدمها لمعرفة متى يتم تحديدها.

استمتعتُ كثيرًا بكتابة هذا. كثيرًا جدًا.

المزيد من تحسينات JavaScript

والجدير بالتذكير أن جوهر ما أوضحه لك هنا يعمل دون JavaScript. وبهذا يمكننا القول، دعونا نرى كيف يمكننا تحسينه عندما تكون لغة JavaScript المتوفرة.

تُعد الروابط لصفحات معيّنة في التطبيق مصطلحًا مخصصًا للأجهزة الجوّالة، ولكنني أعتقد أنّ الغرض من هذا الرابط هنا مع علامات تبويب حيث يمكنك مشاركة عنوان URL مباشرة إلى محتويات علامة التبويب. تشير رسالة الأشكال البيانية سينتقل داخل الصفحة إلى رقم التعريف المطابق في تجزئة عنوان URL. وجدتُ أدّى معالِج onload هذا إلى التأثير في جميع الأنظمة الأساسية.

window.onload = () => {
  if (location.hash) {
    tabsection.scrollLeft = document
      .querySelector(location.hash)
      .offsetLeft;
  }
}

مزامنة إنهاء الانتقال

لا ينقر المستخدمون دائمًا على لوحة مفاتيح أو يستخدمونها، وأحيانًا تكون مجرد التمرير المجاني، كما ينبغي أن يكونوا قادرين على ذلك. عندما يتوقف شريط تمرير القسم التمرير، حيثما تصل، يلزم مطابقتها في شريط التنقل العلوي.

إليك الطريقة التي أنتظر بها نهاية التمرير: js tabsection.addEventListener('scroll', () => { clearTimeout(tabsection.scrollEndTimer); tabsection.scrollEndTimer = setTimeout(determineActiveTabSection, 100); });

وعندما يتم تمرير الأقسام، امسح مهلة القسم إن كانت موجودة، وبدء مسيرة جديدة. وعندما يتوقف تمرير الأقسام، لا تمسح المهلة، وإطفاء لمدة 100 ملّي ثانية بعد الاستراحة. عند تنشيطها، قم باستدعاء الدالة التي تسعى إلى معرفة من حيث توقف المستخدم.

const determineActiveTabSection = () => {
  const i = tabsection.scrollLeft / tabsection.clientWidth;
  const matchingNavItem = tabnavitems[i];

  matchingNavItem && setActiveTab(matchingNavItem);
};

بافتراض أنه قد تم اقتطاع التمرير، يتم تقسيم موضع التمرير الحالي من العرض في منطقة التمرير إلى عدد صحيح وليس عددًا عشريًا. ثم أحاول وجلب عنصر التنقل من ذاكرة التخزين المؤقت عبر هذا الفهرس المحسوب، وإذا وجد شيء ما، سأرسل المطابقة لتكون نشطة.

const setActiveTab = tabbtn => {
  tabnav
    .querySelector(':scope a[active]')
    .removeAttribute('active');

  tabbtn.setAttribute('active', '');
  tabbtn.scrollIntoView();
};

يبدأ إعداد علامة التبويب النشطة بمحو أي علامة تبويب نشطة حاليًا، ثم عنصر التنقل الوارد بسمة الحالة النشطة. المكالمة إلى "scrollIntoView()" وله تفاعل ممتع مع CSS ومن الجدير بالذكر.

.scroll-snap-x {
  overflow: auto hidden;
  overscroll-behavior-x: contain;
  scroll-snap-type: x mandatory;

  @media (prefers-reduced-motion: no-preference) {
    scroll-behavior: smooth;
  }
}

في أداة CSS ذات المحاذاة الأفقية، دمج استعلام وسائط ينطبق smooth يمكن الانتقال للأسفل إذا كان المستخدم يستطيع الحركة. يمكن لـ JavaScript أن تجعل الطلبات تمرير العناصر إلى العرض، ويمكن لـ CSS إدارة تجربة المستخدم بشكل بيان. المطابقة الصغيرة الممتعة التي يصنعونها أحيانًا

الخاتمة

والآن بعد أن عرفت كيف فعلت ذلك، كيف حالك؟! هذا للحصول على بعض المرح بنية المكونات! من سينشئ الإصدار الأول مع إتاحة خانات في اللعبة إطار العمل المفضل لديك؟ 🙂

يمكننا تنويع أساليبنا وتعلُّم جميع طرق إنشاء المحتوى على الويب. إنشاء خطأ تغريدي وسأضيفه إلى الريمكسات في المنتدى أدناه.

ريمكسات من إنشاء المنتدى