إضافة تأثيرات الدخول والخروج إلى العناصر عند دخولها إلى منفذ الانتقال أو الخروج منه

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

كيفية الإعداد

لإضافة تأثيرات الدخول والخروج إلى عنصر، عليك دمج بعض سمات CSS. إليك دليل مفصّل:

  1. أنشئ @keyframes منفصلة لحركات الدخول والخروج. سيتم تطبيق حركة الدخول عند دخول العنصر إلى إطار العرض، وسيتم تطبيق حركة الخروج عند مغادرته.

    @keyframes slide-in {
      from { transform: translateX(-100%); }
    }
    @keyframes slide-out {
      to { transform: translateX(100%); }
    }
    
  2. أرفِق الإطارات الرئيسية للدخول والخروج بالعنصر. يمكنك إجراء ذلك من خلال تحديد حركات متعدّدة في السمة animation.

    • امنح حركة الدخول animation-fill-mode بقيمة backwards ليتم تطبيق حالتها الأولية قبل بدء الحركة.
    • امنح الحركة النهائية animation-fill-mode بقيمة forwards لكي تحافظ على حالتها النهائية بعد اكتمال الحركة.
    .animated-element {
      animation:
        slide-in 1s linear backwards,
        slide-out 1s linear forwards;
    }
    
  3. أنشئ View Timeline واربطه بالصور المتحركة. "المخطط الزمني للعرض" هو نوع من المخططات الزمنية المرتبطة بظهور عنصر في إطار العرض. يمكنك إنشاء دالة باستخدام الدالة view() ثم تطبيقها على الصور المتحركة باستخدام السمة animation-timeline.

    .animated-element {
      animation-timeline: view();
    }
    

    يتتبّع view() تلقائيًا العنصر على المحور block. إذا كنت بحاجة إلى تتبُّعها على المحور inline، يمكنك استخدام view(inline).

  4. يمكنك حصر الصور المتحركة في النطاقَين entry وexit. تتيح لك السمة animation-range تحديد الجزء من المخطط الزمني الذي يجب تشغيل الحركة فيه.

    • يغطي نطاق entry الوقت من لحظة دخول العنصر إلى إطار العرض لأول مرة حتى يصبح مرئيًا بالكامل.
    • يغطي النطاق exit الوقت من بداية مغادرة العنصر لإطار العرض حتى يتم إخفاؤه تمامًا.
    .animated-element {
      animation-range: entry, exit;
    }
    

مثال على الرمز

تُحرِّك هذه التعليمة البرمجية العناصر الفرعية المباشرة لشريط التمرير عند التمرير باستخدام مخطط زمني مجهول للعرض:

@media (prefers-reduced-motion: no-preference) {
  @supports ((animation-timeline: view()) and (animation-range: entry)) {
    @keyframes grow {
      from {
        scale: 0.5;
      }
    }
    @keyframes shrink {
      to {
        scale: 0.5;
      }
    }

    .scroller > * {
      animation:
        grow auto linear backwards,
        shrink auto linear forwards;
      animation-timeline: view(inline);
      animation-range: entry, exit;
    }
  }
}

عندما تدخل العناصر إلى منفذ الانتقال، يتم تشغيل الحركة grow، وعندما تغادر منفذ الانتقال، يتم تشغيل الحركة shrink.

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

@media (prefers-reduced-motion: no-preference) {
  @supports ((animation-timeline: view()) and (animation-range: entry)) {
    @keyframes grow {
      from {
        scale: 0.5;
      }
    }
    @keyframes shrink {
      to {
        scale: 0.5;
      }
    }

    .scroller > * {
      view-timeline: --tl inline;
      animation:
        grow auto linear backwards,
        shrink auto linear forwards;
      animation-timeline: --tl;
      animation-range: entry, exit;
    }
  }
}

أفضل الممارسات

عند استخدام الصور المتحركة المستندة إلى الانتقال، من المهم اتّباع بعض أفضل الممارسات لضمان تجربة سلسة وسهلة الاستخدام:

  • يجب تضمين ميزة رصد الميزات: لا تتيح بعض المتصفّحات استخدام الصور المتحركة المستندة إلى الانتقال للأعلى أو للأسفل. استخدِم @supports ((animation-timeline: view()) and (animation-range: entry)) للتحقّق من توفّر الدعم وتوفير خيار احتياطي للمتصفّحات التي لا تتيح هذه الميزة.
    • يجب تضمين عملية التحقّق من (animation-range: entry) هنا لفلترة المتصفّحات التي توفّر دعمًا جزئيًا فقط.
    • لا تستخدِم حزمة scroll-timeline-polyfill لاستراتيجية الاحتياط لأنّها لا تتضمّن جميع الميزات وتحتوي على الكثير من المشاكل المعروفة.
    • إذا كانت الحركة تُعتبر زخرفية فقط، فاختَر "التحسين التدريجي" ولا تقدّم بديلاً.
  • يجب احترام الإعدادات المفضّلة للمستخدمين: يفضّل بعض المستخدمين تقليل الحركة على الويب. استخدِم الاستعلام عن الوسائط prefers-reduced-motion لإيقاف الصور المتحركة أو تقليلها لهؤلاء المستخدمين.
  • يُرجى محاولة تحريك خصائص CSS ذات الأداء العالي فقط: للحصول على صور متحركة أكثر سلاسة، التزِم بتحريك الخصائص التي يمكن معالجتها من خلال سلسلة عمليات التجميع في المتصفّح، مثل transform وopacity. قد تؤدي إضافة تأثيرات حركية إلى سمات أخرى، مثل width أو height، إلى حدوث مشاكل في الأداء.
  • يجب استخدام ترتيب التعريف الصحيح: عند استخدام السمة المختصرة animation، يجب تعريف animation-timeline بعدها لمنع السمة المختصرة من إعادة ضبط المخطط الزمني.

عند استخدام الدالة view() لإنشاء تأثير حركي مستند إلى الانتقال:

  • اختياري: حدِّد المحور الذي تريد تتبُّعه: عندما لا تستهدف المحور التلقائي block (كما هو الحال في شريط التمرير الأفقي)، حدِّد المحور الذي تريد تتبُّعه باستخدام view(block) أو view(inline).
  • عندما لا يتم تطبيق الحركة على العنصر الذي يتم تتبُّعه نفسه، استخدِم مخططًا زمنيًا للعرض المسمّى.

عند استخدام السمة view-timeline لإنشاء صورة متحركة مستندة إلى الانتقال للأعلى أو للأسفل:

  • يجب استخدام <dashed-ident> لخدمة CSS في الاسم.
  • اختياري تحديد المحور الذي تريد تتبُّعه: في حال عدم استهداف محور block التلقائي (مثلاً في شريط تمرير أفقي)، حدِّد المحور الذي تريد تتبُّعه باستخدام view-timeline-axis.
  • يجب التأكّد من أنّ نطاق البحث يعمل: عندما لا يكون العنصر الذي يعرّف view-timeline عنصرًا رئيسيًا في الشجرة المسطّحة للعنصر المتحرّك، يمكنك رفع مستوى ظهور اسم view-timeline باستخدام timeline-scope على عنصر رئيسي مشترك.

يُفضَّل استخدام view-timeline مسمّى عندما تحتاج عناصر متعددة أو عناصر فرعية من الموضوع الذي يتم تتبُّعه إلى إضافة تأثيرات حركية.

توافق المتصفّح واستراتيجيات الاحتياط

لذلك، عادةً ما تكون هناك حاجة إلى استراتيجية احتياطية.

بالنسبة إلى المتصفّحات التي لا تتيح استخدام الصور المتحركة المستندة إلى الانتقال للأعلى أو للأسفل، يمكنك استخدام خيار احتياطي لإعادة إنشاء التأثيرات المرئية. يتم عادةً إنشاء الإجراءات الاحتياطية باستخدام أداة استماع للتمرير (لتأثيرات ScrollTimeline) أو واجهة برمجة التطبيقات IntersectionObserver (لتأثيرات ViewTimeline).

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

يُرجى العِلم أنّه لا يمكن إعادة إنشاء كل تأثير باستخدام نهج الإجراءات الاحتياطية.

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

<script>
  if (!CSS.supports('(animation-timeline: view()) and (animation-range: entry)')) {
    const observer = new IntersectionObserver(
      (entries) => {
        for (const entry of entries) {
          // This matches the effect as defined in the CSS example above.
          // Customize this further if needed.
          entry.target.style.scale = 0.5 + entry.intersectionRatio * 0.5;
        }
      },
      {
        threshold: Array.from({ length: 101 }, (_, i) => i / 100),
      }
    );

    document.querySelectorAll('.scroller > *').forEach((el) => {
      observer.observe(el);
    });
  }
</script>