تخطّى إلى المحتوى الرئيسي
انتقالات العرض في Next.js: تحريك تغيّرات الصفحات والعناصر دون مكتبة

انتقالات العرض في Next.js: تحريك تغيّرات الصفحات والعناصر دون مكتبة

July 16, 2026
هندسة الواجهات
5 دقيقة قراءة

أبرز النقاط

واجهة View Transitions تُحرّك الانتقال بين حالتين للـ DOM عند استدعاء document.startViewTransition(updateDOM)؛ إذ يلتقط المتصفح لقطة للصفحة قبل التحديث وبعده ثم يُحرّك الفرق بينهما.

الانتقال الافتراضي هو تلاشٍ متبادل للصفحة كاملة باسم root، وإسناد view-transition-name إلى عنصر يجعله يتحرك بشكل مستقل كمجموعته الخاصة.

لتنقّلات App Router في Next.js على جهة العميل، يغلّف فريقنا استدعاء router.push داخل document.startViewTransition، أو يُفعّل مكوّن ViewTransition المدمج في React خلف علم experimental.viewTransition.

لا يزال مكوّن ViewTransition في React تجريبيًا في إصدارات React 19.x، فهو اختياري خلف علم وليس جزءًا من الواجهة المستقرة.

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

ما هي واجهة View Transitions وأي مشكلة تحل؟

واجهة View Transitions هي واجهة برمجية في المتصفح تُحرّك التغيّر البصري بين حالتين للـ DOM. قبل وجودها كان تحريك تغيّر المسار يعني إبقاء الواجهة القديمة والجديدة معًا في الـ DOM، وتنسيق أصناف CSS، ثم تنظيفها بعد ذلك — وهو عمليًا مهمة مكتبة كاملة.

في Devya استبدلنا هذه الآلية بالواجهة الأصلية. تستدعي document.startViewTransition(callback)، فيلتقط المتصفح لقطة للصفحة الحالية، ثم يشغّل الـ callback لتحديث الـ DOM، ثم يلتقط لقطة للحالة الجديدة، ويُجري تلاشيًا متبادلًا بين اللقطتين. وصلت انتقالات نفس المستند في Chrome 111 في مارس 2023، ووصلت انتقالات المستندات المتقاطعة في Chrome 126 في يونيو 2024، وأضافت Firefox وSafari واجهة نفس المستند منذ ذلك الحين.

كيف نشغّل أول انتقال؟

استدعِ document.startViewTransition() ومرّر callback يعدّل الـ DOM؛ والحركة الافتراضية هي تلاشٍ متبادل للصفحة كاملة يستغرق ربع ثانية. تحقّق أولًا من وجود الدالة، لأنها غير معرّفة في المتصفحات غير الداعمة، واستدعاء التحديث مباشرة هو البديل الصحيح.

تُعيد الدالة كائن ViewTransition يحمل ثلاثة وعود: updateCallbackDone عند تشغيل الـ callback، وready عند بناء العناصر الوهمية وقرب بدء الحركة، وfinished عند انتهاء الحركة. انتظار finished يتيح تشغيل شيفرتنا بعد اكتمال الانتقال.

كيف نحرّك عنصرًا واحدًا بشكل مستقل؟

امنح العنصر قيمة view-transition-name فريدة في CSS، فيحرّكه المتصفح كمجموعته الخاصة بدلًا من دمجه في تلاشي الصفحة. هذا ما يُنتج تأثير العنصر المشترك، حيث تكبر صورة مصغّرة لتتحول إلى صورة رئيسية عبر التنقّل.

أثناء الانتقال يبني المتصفح عناصر وهمية يمكن لأنماطنا استهدافها: ::view-transition-old(name) هي اللقطة الخارجة، و::view-transition-new(name) هي الداخلة، و::view-transition-group(name) يغلّف كليهما ويحرّك الموضع والحجم. ويُسنَد الاسم root إلى المستند كاملًا افتراضيًا، لذا يستهدف ::view-transition-old(root) تلاشي الصفحة كاملة.

كيف نضيف انتقالات العرض إلى تنقّل App Router في Next.js؟

غلّف التنقّل داخل document.startViewTransition ليصبح تحديث الـ DOM الذي تنفّذه React أثناء تغيّر المسار هو الـ callback الخاص بالانتقال. ولأن router.push غير متزامن، فالنمط الموثوق هو خطّاف عميل صغير يستدعي document.startViewTransition مع callback يدفع المسار الجديد، ويعود إلى دفع عادي عند غياب الواجهة.

لانتقالات المستندات المتقاطعة في موقع مُصدَّر ثابتًا أو متعدد الصفحات، لا حاجة إلى أي JavaScript: فعّلها عبر قاعدة CSS @view-transition { navigation: auto; } في صفحتي المصدر والوجهة معًا. وتغلّف حزمة next-view-transitions المجتمعية نمط العميل للفرق التي تفضّل عدم كتابة الخطّاف بنفسها.

ما هو مكوّن ViewTransition في React وهل هو جاهز؟

ViewTransition مكوّن React تجريبي يحرّك أبناءه عند دخولهم أو خروجهم أو إعادة ترتيبهم نتيجة انتقال أو تحلّل حدّ Suspense. فبدلًا من استدعاء document.startViewTransition مباشرة، تغلّف الواجهة المتغيّرة وتقود React الواجهة نيابةً عنك.

لا يزال تجريبيًا في React 19.x: الاستيراد مسبوق بـ unstable_ViewTransition، وفي Next.js يُفعَّل بضبط experimental.viewTransition على true في next.config. في Devya نشحن أسلوب document.startViewTransition المباشر في الإنتاج لأنه واجهة متصفح مستقرة، ونحتفظ بمكوّن React للنماذج الأولية حتى يصل إلى إصدار مستقر. والمقايضة واضحة: مكوّن React يمنح حركات دخول وخروج مرتبطة بشجرة المكوّنات، بينما تمنح الواجهة الخام الاستقرار اليوم.

ما الذي يتعطّل — الأسماء المكرّرة وتقليل الحركة والأداء

العطل الأكثر شيوعًا هو مشاركة عنصرين لاسم view-transition-name واحد في اللقطة نفسها؛ إذ لا يستطيع المتصفح تحديد أيّهما يحوّل، فيتخطّى الانتقال ويسجّل تحذيرًا. في القوائم، أسند اسمًا مشتقًّا من معرّف فريد وفقط للعنصر الذي ينتقل فعلًا.

احترم prefers-reduced-motion، لأن الواجهة تُحرّك، ومن يطلبون حركة أقل ينبغي أن يحصلوا على تحديث فوري؛ ويكفي تعطيل الحركة على العناصر الوهمية للانتقال داخل ذلك الاستعلام. أما الأداء، فالحالتان القديمة والجديدة تُرسَمان كلقطتين وتحرّكهما المجموعة بتحويلات transform يعالجها المركّب بكلفة زهيدة، لكن اللقطات الكبيرة بملء الشاشة على الأجهزة الضعيفة قد تكلّف إطارات — لذا نقصر الانتقالات المسمّاة بشكل مستقل على العناصر التي تحتاج فعلًا إلى الحركة ونترك الباقي على التلاشي الافتراضي.

الأسئلة الشائعة

ما المتصفحات التي تدعم واجهة View Transitions؟

وصلت انتقالات نفس المستند في Chrome 111 في مارس 2023 وهي الآن في Firefox وSafari، ووصلت انتقالات المستندات المتقاطعة في Chrome 126 في يونيو 2024. تحقّق دائمًا من وجود document.startViewTransition.

هل نحتاج مكتبة لاستخدام انتقالات العرض في Next.js؟

لا. تغليف router.push داخل document.startViewTransition يغطّي تنقّلات العميل دون أي اعتمادية، ومكتبات مثل next-view-transitions تغلّف هذا النمط فقط.

لماذا لم يتحرّك انتقال العرض؟

السبب الأكثر شيوعًا هو وجود عنصرين بنفس view-transition-name في لقطة واحدة، ما يدفع المتصفح إلى تخطّي الانتقال. يجب أن تكون الأسماء فريدة في كل حالة ملتقَطة.

هل مكوّن ViewTransition في React مستقر؟

لا. حتى React 19.x هو تجريبي، يُستورد باسم unstable_ViewTransition ويُفعَّل في Next.js خلف experimental.viewTransition. استخدم واجهة المتصفح مباشرة في الإنتاج.

هل يمكن لانتقالات العرض تحريك خصائص التخطيط مثل العرض والارتفاع؟

نعم، عبر ::view-transition-group الذي يحرّك الحجم والموضع بين اللقطتين. أبقِ الحركات الأثقل على transform وopacity قدر الإمكان، لأن الحالتين القديمة والجديدة تُرسَمان كصور.