إنشاء مكوِّن القصص

نظرة عامة أساسية حول كيفية إنشاء تجربة مشابهة لـ "قصص Instagram" على الويب

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

الإصدار التجريبي

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

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

نظرة عامة

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

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

اختيار الأدوات المناسبة للوظيفة

بوجهٍ عام، تبيّن لي أنّه من السهل جدًا إنشاء هذا المكوّن، وذلك بفضل بعض الميزات المهمة لمنصّة الويب. دعونا نتناولها!

شبكة CSS

تبيّن أنّ تنسيقنا ليس صعبًا على CSS Grid لأنّه مزوّد ببعض الطرق الفعّالة لتنظيم المحتوى.

تنسيق الأصدقاء

إنّ الغلاف الأساسي لمكوّن .stories هو عرض أفقي للانتقال للأعلى أو للأسفل يناسب الأجهزة الجوّالة:

.stories {
  inline-size: 100vw;
  block-size: 100vh;

  display: grid;
  grid: 1fr / auto-flow 100%;
  gap: 1ch;

  overflow-x: auto;
  scroll-snap-type: x mandatory;
  overscroll-behavior: contain;
  touch-action: pan-x;
}

/* desktop constraint */
@media (hover: hover) and (min-width: 480px) {
  max-inline-size: 480px;
  max-block-size: 848px;
}
استخدام وضع الجهاز في "أدوات مطوّري البرامج في Chrome"

دعنا نفصّل تنسيق grid هذا:

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

التجميع

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

باستخدام شبكة CSS، يمكننا تحديد شبكة خلية واحدة (أي مربّع)، حيث تشترك الصفوف والأعمدة في اسم بديل ([story])، ثم يتم تعيين كل عنصر فرعي إلى تلك المساحة التي تحمل اسم بديلًا للخلية الواحدة:

.user {
  display: grid;
  grid: [story] 1fr / [story] 1fr;
  scroll-snap-align: start;
  scroll-snap-stop: always;
}
.story {
  grid-area: story;
  background-size: cover;
  
}

يتيح ذلك لـ HTML التحكم في ترتيب التكديس ويحافظ أيضًا على تدفق جميع العناصر. لاحظ أننا لم نحتاج إلى اتخاذ أي إجراء بشأن موضع absolute أو z-index ولم نحتاج إلى ضبط المربع باستخدام height: 100% أو width: 100%. لقد حدّدت الشبكة الرئيسية حجم إطار عرض صورة القصة، لذا لم يكن من الضروري تحديد أيّ من مكوّنات القصة لملئه.

نقاط التصاق التمرير في CSS

تُسهّل مواصفات نقاط التصاق التمرير في CSS قفل العناصر في إطار العرض عند التمرير. قبل توفّر سمات CSS هذه، كان عليك استخدام JavaScript، وكان ذلك أمرًا صعبًا على أقل تقدير. ما عليك سوى الاطّلاع على نبذة عن نقاط Snap Scroll Snap في صفحات الأنماط المتتالية (CSS) من إعداد "سارة دراسنر" للحصول على معلومات مفصّلة حول كيفية استخدامها.

التمرير الأفقي بدون أنماط scroll-snap-points ومعها بدونه، يمكن للمستخدمين حرية التمرير كالمعتاد. في هذه الحالة، ينحني المتصفح برفق على كل عنصر.
عنصر رئيسي
.stories {
  display: grid;
  grid: 1fr / auto-flow 100%;
  gap: 1ch;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  overscroll-behavior: contain;
  touch-action: pan-x;
}
يحدّد العنصر الرئيسي الذي يستخدم تمريرًا زائدًا سلوك المحاذاة.
طفل
.user {
  display: grid;
  grid: [story] 1fr / [story] 1fr;
  scroll-snap-align: start;
  scroll-snap-stop: always;
}
يوافق الأطفال على أن يكونوا هدفًا للصور المصغّرة.

لقد اخترت Scroll Snap Points لعدة أسباب:

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

التوافق مع جميع المتصفّحات

اختبرنا على Opera وFirefox وSafari وChrome بالإضافة إلى نظامي التشغيل Android وiOS. في ما يلي ملخّص موجز عن ميزات الويب التي تبيّن لنا أنّها تختلف في الإمكانات والدعم.

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

scroll-snap-stop

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

.user {
  scroll-snap-align: start;
  scroll-snap-stop: always;
}

في وقت كتابة هذه المشاركة، كان scroll-snap-stop متوافقًا فقط على المتصفحات المستندة إلى Chromium. يمكنك الاطّلاع على توافق المتصفّح للحصول على آخر المعلومات. ومع ذلك، لا يمنع ذلك من إتمام عملية الدفع. هذا يعني فقط أنّه على المتصفحات غير المتوافقة، يمكن للمستخدمين تخطّي صديق عن طريق الخطأ. لذلك، على المستخدمين أن يكونوا أكثر حرصًا، أو علينا كتابة JavaScript لضمان عدم وضع علامة "تمت المشاهدة" على صديق تم تخطّيه.

يمكنك الاطّلاع على المزيد من المعلومات في المواصفات إذا كنت مهتمًا.

overscroll-behavior

هل سبق لك أن كنت تنتقل في نافذة منبثقة ثم فجأة بدأت في الانتقال إلى المحتوى الظاهر خلف النافذة المنبثقة؟ overscroll-behavior يسمح هذا الإجراء للمطوّر بحظر الانتقال إلى أعلى الصفحة وعدم السماح أبدًا بتركها. وهو مناسب لجميع أنواع المناسبات. يستخدم مكوّن "قصصي" هذه السمة لمنع التمريرات السريعة وإيماءات الانتقال إلى الأعلى أو الأسفل الإضافية من مغادرة المكوّن.

.stories {
  overflow-x: auto;
  overscroll-behavior: contain;
}

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

scrollIntoView({behavior: 'smooth'})

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

element.scrollIntoView({
  behavior: 'smooth'
})

كان Safari المتصفّح الوحيد الذي لا يدعم behavior: 'smooth' هنا. يمكنك الاطّلاع على توافق المتصفّح للحصول على آخر المعلومات.

التدريب العملي

الآن بعد أن عرفت كيف فعلت ذلك، كيف ستفعل ذلك؟ يمكننا تنويع أساليبنا ونتعلم جميع طرق إنشاء المحتوى على الويب. أنشئ Glitch، ثمّ أرسِل إلينا تغريدة تتضمّن نسختك، وسنضيفها إلى قسم "الريمكسات التي أنشأها المستخدمون" أدناه.

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