تعد الحركة جزءًا أساسيًا من أي تجربة رقمية، حيث توجه المستخدم من تفاعل إلى آخر. هناك بعض الفجوات في الصور المتحركة المتجانسة على منصة الويب. وتشمل هذه الميزات القدرة على تحريك الرسوم المتحركة للإدخال والخروج بسهولة، بالإضافة إلى التحريك بسلاسة من وإلى الطبقة العلوية للعناصر القابلة للتجاهل، مثل مربّعات الحوار والنوافذ المنبثقة.
لسد هذه الفجوات، يشمل الإصداران Chrome 116 وChrome 117 أربع ميزات جديدة للأنظمة الأساسية للويب، والتي تتيح استخدام صور متحركة وانتقالات سلسة للخصائص المنفصلة.
تشمل هذه الميزات الأربع الجديدة:
- إمكانية تحريك
display
وcontent-visibility
على مخطط زمني للإطار الرئيسي (من Chrome 116) - تشير السمة
transition-behavior
إلى الكلمة الرئيسيةallow-discrete
لتفعيل عمليات نقل الخصائص المنفصلة مثلdisplay
(من Chrome 117). - القاعدة
@starting-style
لتحريك تأثيرات الإدخال منdisplay: none
إلى الطبقة العلوية (من Chrome 117) - السمة
overlay
للتحكم في سلوك الطبقة العلوية أثناء تشغيل صورة متحركة (من Chrome 117).
عرض الصور المتحركة في إطارات رئيسية
من الإصدار 116 من Chrome، يمكنك استخدام display
وcontent-visibility
في قواعد الإطارات الرئيسية. وسيتم تبديلها بعد ذلك في وقت تسجيل الإطار الرئيسي. لا يلزم تقديم قيم جديدة إضافية لإتاحة هذا الخيار:
.card {
animation: fade-out 0.5s forwards;
}
@keyframes fade-out {
100% {
opacity: 0;
display: none;
}
}
يؤدي المثال السابق إلى تحريك التعتيم إلى 0 خلال المدة 0.5 ثانية ثم تعيين العرض على "بلا". بالإضافة إلى ذلك، تضمن الكلمة الرئيسية forwards
بقاء الصورة المتحركة في حالتها النهائية، لكي يبقى العنصر المطبَّق عليه display: none
وopacity: 0
.
هذا مثال بسيط يحاكي ما يمكنك فعله باستخدام الانتقال (راجع العرض التوضيحي في القسم الانتقال). في المقابل، لا يمكن للانتقالات إنشاء رسوم متحركة أكثر تعقيدًا، مثل المثال التالي:
.card {
animation: spin-and-delete 1s ease-in forwards;
}
@keyframes spin-and-delete {
0% {
transform: rotateY(0);
filter: hue-rotate(0);
}
80% {
transform: rotateY(360deg);
filter: hue-rotate(180deg);
opacity: 1;
}
100% {
opacity: 0;
display: none;
}
}
الحركة spin-and-delete
هي صورة متحركة عند الخروج. أولاً، ستدور البطاقة على المحور الصادي، وسيتم إجراؤها من خلال تدوير تدرُّج تدرُّج الألوان، ثم في 80%
خلال المخطط الزمني، يتم تغيير التعتيم لهذه البطاقة من 1 إلى 0. في النهاية، يتمّ تبديل البطاقة من display: block
إلى display: none
.
بالنسبة إلى الرسوم المتحركة للخروج، بدلاً من تطبيقها مباشرةً على عنصر، يمكنك إعداد مشغل للصور المتحركة. على سبيل المثال، من خلال إرفاق أداة معالجة حدث مع زر يؤدّي إلى تطبيق الحركة في الصف، مثل:
.spin-out {
animation: spin-and-delete 1s ease-in forwards;
}
document.querySelector('.delete-btn').addEventListener('click', () => {
document.querySelector('.card').classList.add('spin-out');
})
يحتوي المثال أعلاه الآن على حالة نهاية display:none
. في العديد من الحالات، قد تحتاج إلى إجراء المزيد من العملية وإزالة عقدة DOM مع تحديد مهلة للسماح بإنهاء الرسم المتحرك أولاً.
نقل الصور المتحركة المنفصلة
وعلى عكس ما يحدث عند تحريك خصائص منفصلة باستخدام الإطارات الرئيسية، ستحتاج إلى استخدام وضع سلوك النقل allow-discrete
لنقل الخصائص المنفصلة.
السمة transition-behavior
الوضع allow-discrete
هو ما يجعل الانتقالات المنفصلة ممكنة، وهو قيمة للسمة transition-behavior
. تقبل الدالة transition-behavior
قيمتَين: normal
وallow-discrete
.
.card {
transition: opacity 0.25s, display 0.25s;
transition-behavior: allow-discrete; /* Note: be sure to write this after the shorthand */
}
.card.fade-out {
opacity: 0;
display: none;
}
يحدّد اختصار transition
هذه القيمة أيضًا، لذا يمكنك حذف السمة واستخدام الكلمة الرئيسية allow-discrete
في نهاية الاختصار transition
لكل عملية انتقال بدلاً من ذلك.
.card {
transition: opacity 0.5s, display 0.5s allow-discrete;
}
.card.fade-out {
opacity: 0;
display: none;
}
إذا كنت تريد إضافة تأثيرات متحركة متعددة لخصائص منفصلة، يجب تضمين allow-discrete
بعد كل خاصية تريد تحريكها. على سبيل المثال:
.card {
transition: opacity 0.5s, display 0.5s allow-discrete, overlay 0.5s allow-discrete;
}
.card.fade-out {
opacity: 0;
display: none;
}
القاعدة @starting-style
المتعلّقة بالصور المتحركة للإدخال
تتناول هذه المقالة حتى الآن الصور المتحركة عند الخروج. لإنشاء صور متحركة للإدخالات، عليك استخدام القاعدة @starting-style
.
استخدِم @starting-style
لتطبيق نمط يمكن أن يبحث عنه المتصفّح قبل فتح العنصر على الصفحة. هذه هي حالة "قبل الفتح" (المكان الذي تصوّر فيه).
/* 0. BEFORE-OPEN STATE */
/* Starting point for the transition */
@starting-style {
.item {
opacity: 0;
height: 0;
}
}
/* 1. IS-OPEN STATE */
/* The state at which the element is open + transition logic */
.item {
height: 3rem;
display: grid;
overflow: hidden;
transition: opacity 0.5s, transform 0.5s, height 0.5s, display 0.5s allow-discrete;
}
/* 2. EXITING STATE */
/* While it is deleting, before DOM removal in JS, apply this
transformation for height, opacity, and a transform which
skews the element and moves it to the left before setting
it to display: none */
.is-deleting {
opacity: 0;
height: 0;
display: none;
transform: skewX(50deg) translateX(-25vw);
}
الآن لديك حالة إدخال وخروج لعناصر قائمة المهام هذه:
تحريك العناصر من وإلى الطبقة العلوية
لتحريك العناصر من وإلى الطبقة العلوية، حدِّد @starting-style
على الحالة "فتح" لإعلام المتصفّح بالمكان الذي سيتم إنشاء الحركة منه. في مربّع الحوار، يتم تحديد حالة الفتح باستخدام السمة [open]
. بالنسبة إلى النافذة المنبثقة، استخدِم الفئة الزائفة :popover-open
.
يمكن أن يظهر مثال بسيط لمربّع حوار على النحو التالي:
/* 0. BEFORE-OPEN STATE */
@starting-style {
dialog[open] {
translate: 0 100vh;
}
}
/* 1. IS-OPEN STATE */
dialog[open] {
translate: 0 0;
}
/* 2. EXIT STATE */
dialog {
transition: translate 0.7s ease-out, overlay 0.7s ease-out allow-discrete, display 0.7s ease-out allow-discrete;
translate: 0 100vh;
}
في المثال التالي، يختلف تأثير الإدخال وتأثير الخروج. يمكنك الدخول من خلال تحريك لأعلى من أسفل إطار العرض، ثم الخروج من التأثير إلى أعلى إطار العرض. كما أنه مكتوب باستخدام CSS متداخل لتوفير المزيد من التغليف المرئي.
عند إضافة تأثيرات متحركة إلى نافذة منبثقة، استخدِم الفئة الصورية :popover-open
بدلاً من السمة open
المستخدَمة سابقًا.
.settings-popover {
&:popover-open {
/* 0. BEFORE-OPEN STATE */
/* Initial state for what we're animating *in* from,
in this case: goes from lower (y + 20px) to center */
@starting-style {
transform: translateY(20px);
opacity: 0;
}
/* 1. IS-OPEN STATE */
/* state when popover is open, BOTH:
what we're transitioning *in* to
and transitioning *out* from */
transform: translateY(0);
opacity: 1;
}
/* 2. EXIT STATE */
/* Initial state for what we're animating *out* to ,
in this case: goes from center to (y - 50px) higher */
transform: translateY(-50px);
opacity: 0;
/* Enumerate transitioning properties,
including display and allow-discrete mode */
transition: transform 0.5s, opacity 0.5s, display 0.5s allow-discrete;
}
overlay
الموقع الإلكتروني
أخيرًا، لإخفاء popover
أو dialog
من الطبقة العلوية، أضِف السمة overlay
إلى قائمة الانتقالات. يتخطى popover
وdialog
المقاطع وتحويلات الأصل، ويتم أيضًا وضع المحتوى في الطبقة العلوية. وإذا لم تنقل قيمة overlay
، سيعود العنصر على الفور إلى اقتصاصه وتحويله وتغطيته، ولن تلاحظ حدوث الانتقال.
[open] {
transition: opacity 1s, display 1s allow-discrete;
}
بدلاً من ذلك، يمكنك تضمين overlay
في الانتقال أو الصورة المتحركة لتحريك overlay
مع باقي الميزات وضمان بقائها في الطبقة العليا عند إضافة تأثيرات متحركة. سيبدو هذا أكثر سلاسة.
[open] {
transition: opacity 1s, display 1s allow-discrete, overlay 1s allow-discrete;
}
بالإضافة إلى ذلك، عندما يكون لديك عناصر متعددة مفتوحة في الطبقة العلوية، يساعدك التراكب على التحكم في الانتقال السلس من وإلى الطبقة العلوية. يمكنك معرفة الفرق في هذا المثال البسيط. إذا لم يتم تطبيق overlay
على العنصر المنبثق الثاني عند نقله، فسيتم نقله أولاً من الطبقة العلوية، حيث يقفز خلف النافذة المنبثقة الأخرى، قبل بدء عملية الانتقال. وهذا ليس تأثيرًا سلسًا جدًا.
ملاحظة حول انتقالات العرض
في حال إجراء تغييرات على نموذج العناصر في المستند (DOM)، مثل إضافة عناصر وإزالتها من نموذج العناصر في المستند (DOM)، هناك حل رائع آخر للصور المتحركة المتجانسة، وهو انتقالات العرض. في ما يلي مثالان أعلاه تم إنشاؤهما باستخدام انتقالات العرض.
في هذا العرض التوضيحي الأول، ستعالج انتقالات العرض عملية النقل، بدلاً من إعداد @starting-style
وعمليات تحويل CSS الأخرى. يتم إعداد انتقال العرض على النحو التالي:
أولاً، في خدمة مقارنة الأسعار (CSS)، يجب تخصيص view-transition-name
فردي لكل بطاقة.
.card-1 {
view-transition-name: card-1;
}
.card-2 {
view-transition-name: card-2;
}
/* etc. */
بعد ذلك، في JavaScript، عليك إحاطة تغيُّر DOM (في هذه الحالة، إزالة البطاقة)، في انتقال طريقة العرض.
deleteBtn.addEventListener('click', () => {
// Check for browser support
if (document.startViewTransition) {
document.startViewTransition(() => {
// DOM mutation
card.remove();
});
}
// Alternative if no browser support
else {
card.remove();
}
})
أما الآن، فيمكن للمتصفح التعامل مع التلاشي للخارج والتغير في كل بطاقة إلى موضعها الجديد.
مثال آخر على حيث يمكن أن يكون هذا مفيدًا من خلال العرض التوضيحي لإضافة/إزالة عناصر القائمة. وفي هذه الحالة، عليك إضافة view-transition-name
فريد لكل بطاقة يتم إنشاؤها.
الخاتمة
تقرّبنا هذه الميزات الجديدة على النظام الأساسي من عملية الدخول والخروج بسلاسة من الصور المتحركة على النظام الأساسي للويب. لمزيد من المعلومات، راجع الروابط التالية: