الرسوم المتحركة animations في CSS
هل تصدق أن بإمكانك إنشاء تطبيقات متحركة بإستخدام CSS فقط ؟!
تقديم
كتب هذا المقال أشرف عبدالدايم مطور واجهة المستخدم في TieLabs سابقاً، 95% من كود CSS الموجود في قالب جنة من كتابة أشرف :)
قبل إضافة الخاصية animation للغة CSS كانت جميع عناصر صفحة الويب تظهر بشكل ثابت بدون أي حركة، وكنا عندما نريد إضافة حركة لبعض عناصر الصفحة نلجأ دائماً لإستخدام لغة Javascript (إحدى التقنيات الثلاثة الأساسية للويب – HTML / CSS / Javascript) ويتم هذا بربط احدى مكتبات Javascript في صفحة الويب (من أشرهم على الإطلاق مكتبة jQuery) أو أحدى المكتبات الأخرى المتخصصة في حركة العناصر. وفي كل حال مزيد من الملفات المربوطة بصفحة الويب، ومزيد من الأكواد، يعني زيادة في وقت تحميل الصفحة، وهذا ما نسعى دائماً لتحسينه.
بعد إضافة خاصية animation للغة CSS أصبح من الممكن الإستغناء عن لغة Javascript (فيما يخص الجزء المتعلق بحركة العناصر فقط، فلغة Javascript لها العديد من الوظائف الأخرى التي يجعل من الصعب استغناء صفحة الويب عنها، فهي لغة البرمجة الأكثر استخداماً الآن).
في مقال سابق تحدثنا عن الخاصية transition وهي أيضاً متعلقة بحركة العناصر، فما الفرق بينها وبين الخاصية animation؟
الخاصية transition هي طريقة لتحريك العناصر من حالة لأخرى (من حالة البداية إلى حالة النهاية) إذا فهي نوع محدد من الخاصية animation، حيث:
- لديها حالتين فقط، حالة البداية وحالة النهاية.
- لا يمكنك تكرار الحركة.
- لا يمكنك التحكم في الحالات البينة بين حالة البداية وحالة النهاية إلإ بإستخدام دالة نوع الحركة Timing Function فقط.
لكن ماذا لو كنت تريد:
- التحكم في حركة الحالات البينية؟ أي عندما تكون الحركة في المنتصف مثلاً نقوم بتغير خصائص معينة للعنصر، ليس فقط في بداية الحركة أو نهايتها.
- تكرار حركة العنصر، والتحكم في عدد مرات التكرار؟
- حركات مختلفة لنفس العنصر؟
- أنواع حركات مختلفة Timing Functions لخصائص مخلتفة؟
كل هذة الأشياء وأكثر يمكن للخاصية animation تحقيقها بكل سهولة، لك أن تتخيل أن الخاصيةanimation عبارة عن فيلم قصير، وأنت مخرج هذا الفيلم الذي يقوم بإعطاء الأوامر (CSS Rules) للمثلين (عناصر HTML) لتنفيذ المشاهد المختلفة (keyframes).
في هذا المقال سنقوم بتوضيح المفاهيم الأساسية لتأثير الحركة في CSS من خلال شرح الخصائص المتعلقة بالخاصية animation
بناء الرسوم المتحركة
بناء الرسوم المتحركة في CSS يتكون من جزئين أساسين:
- القاعدة @keyframes : تتحكم في مراحل الحركة والخصائص التي سيتم تحريكها.
- خصائص الحركة Animation Properties: بإضافة إسم القاعدة @keyframes لعنصر محدد وتحديد كيفية إتمام الحركة.
دعنا نلقي نظرة على كل منهما على حده.
الجزء الاول: القاعدة @keyframes
القاعدة @keyframes هي أساس الرسوم المتحركة في CSS، فهي تحدد كيف ستبدو الحركة في كل مرحلة في الخط الزمني للحركة، كل قاعدة @keyframes تتكون من:
- إسم الحركة: اسم وصفي للحركة، على سبيل المثال bouncing.
- مراحل الحركة: كل مرحلة من مراحل الحركة يتم تمثيلها بالنسبة المئوية، 0% تعني بداية الحركة، 50% تعني منتصف الخط الزمني للحركة، 100% تعني نهاية الحركة، ويمكنك إضافة مراحل بينية كما تشاء.
- خصائص العنصر: خصائص CSS التي سيتم إضافتها لكل مرحلة من الحركة على الخط الزمني للحركة.
دعنا نلقي نظرة على كيفية استخدام القاعدة @keyframes، قمنا بتسميتها بالإسم bouncing على سبيل المثال، وهذة القاعدة لديها ثلاثة مراحلة، المرحلة الأولى ( 0% ) ، يكون العنصر بدرجة شفافية صفر (غير مرئي) وتم تقليص حجمة لعشر حجمه الأصلي بإستخدام التصريح transfrom: scale(0.1). المرحلة الثانية ( 60% ) سيظهر العنصر بشكل تدريجي (fade) لتصبح درجة الشفافية ١ (أي مرئي بشكل كامل) وزيادة ججمة بنسبة ١.٢ من حجمه الأصلي، في المرحلة الثالثة والأخيرة ( 100% ) سيتم تقليصه مرة ثانية لحجمه الأصلي.
يتم إضافة القاعدة @keyframes إلى ملف التنسيق لديك، كالتالي:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | @keyframes bouncing { 0% { transform: scale(0.1); opacity: 0; } 60% { transform: scale(1.2); opacity: 1; } 100% { transform: scale(1); } } |
See the Pen animation #1 by Ashraf Reda (@ashrafreda) on CodePen.
لاحظ أن العنصر إلى الآن يظهر بشكل ثابت، دعنا ننتقل للجزء التالي لنتعرف على كيفية ربط القاعدة @keyframes بباقي خصائص الحركة.
الجزء الثاني: خصائص الحركة Animation Properties
بعد أن قمت بتعين القاعدة @keyframes، إذا يجب إضافة خصائص الحركة لكي تعمل الرسوم المتحركة، خصائص الحركة تقوم بوظيفتين:
- تقوم بتعيين إسم القاعدة @keyframes التي قمنا بتعريفها من قبل وسنقوم بإستخدامها على العنصر المُراد تطبيق الحركة عليه.
- تقوم بتحديد كيفية إتمام هذة الحركة (مدة الحركة، مدة الإنتظار، منحنى الحركة، عدد مرات التكرار، وهكذا..).
هناك العديد من الخصائص المتعلقة بالرسوم المتحركة، لكن يجب عليك بشكل إلزامي إضافة هاتين الخاصيتين كي تعمل الحركة:
- خاصية إسم الحركة animation-name : إسم الحركة الذي تم تعينه مع القاعدة @keyframes.
- خاصية مدة الحركة animation-duration : مدة الحركة بالثانية (مثل 5s) أو المللي ثانية (مثل 5000ms).
وإتماماً للمثال السابق، نريد تطبيق الحركة المسماه بـ bouncing على العنصر <h1>، سنقوم بإضافة الخصائص الإلزامية animation-name و animation-duration للعنصر كالتالي:
1 2 3 4 5 6 | h1 { animation-duration: 0.5s; animation-name: bouncing; } |
أو بالخاصية المختصرة animation كالتالي:
1 2 3 4 5 | h1 { animation: bouncing 0.5s; } |
بإضفة القاعدة @keyframes وخصائص الحركة، ستكون النتيجة كالتالي: (حيث أن الحركة لا تتكرر، إضغط على الزر Return لإعادة تشغيلها مرةً ثانية)
See the Pen animation #2 by Ashraf Reda (@ashrafreda) on CodePen.
مثل الخاصية transition، فإن الخاصية animation عبارة عن اختصار لمجموعة متعددة من خواص الحركة الأخرى:
- animation-name : إسم الحركة.
- animation-duration : إلى متى ستستمر الحركة (مدة الحركة).
- animation-timing-function : كيف سيتم حساب الحالات البينية (نوع أو شكل الحركة خلال خط الزمن).
- animation-delay : عندما تريد بداية الحركة بعد مدة زمنية محددة (فترة إنتظار).
- animation-iteration-count : عدد مرات تكرار الحركة.
- animation-direction : يحدد إتجاة الحركة (في أي اتجاة سيتم قراءة المراحل داخل القاعدة @keyframes ).
- animation-fill-mode : أي التنسيقات سيتم تطبيقها قبل بداية الحركة وبعد نهايتها.
الخاصية animation المختصرة
يمكنك استخدام كل خاصية من خصائص الحركة بكشل منفرد، لكن من أجل الإختصار والسرعة في كتابة الأكواد يفضل دائماً إستخدام الخصائص المختصرة، يمكنك دمج كل خصائص الحركة في الخاصية animation المختصرة هكذا:
1 2 3 | animation: [animation-name] [animation-duration] [animation-timing-function] [animation-delay] [animation-iteration-count] [animation-direction] [animation-fill-mode] [animation-play-state]; |
ولكي تعمل الحركة يجيب ترتيب الخواص هكذا، وتعيين قيم أول خاصيتين على الأقل.
مثال
تخيل زر التحميل التالي:
See the Pen animation #3 by Ashraf Reda (@ashrafreda) on CodePen.
تخيل شكل الزر في المثال السابق! زر ثابت، لا يوحي بأي معنى سوى كلمة “تحميل…” ماذا لو قمنا بتطبيق نوع من الحركة يوحي بأنه زر تحميل، هكذا:
See the Pen animation #4 by Ashraf Reda (@ashrafreda) on CodePen.
لقد اختلف الأمر كثيراً، لقد أضفى تأثر الحركة نوع من الحياة على العنصر، لقد جذب المزيد من الإنتباه.
في المثال السابق، قمنا باستخدام الخاصية المختصرة animation التي تتضمن الخصائص التالية:
- animation-name : إسم الحركة، في هذا المثال bouncing
- animation-duration : نصف ثانية 0.5s
- animation-timing-function : الدالة cubic-bezier(0.1,0.25,0.1,1)
- animation-delay : بدون انتظار 0s
- animation-iteration-count : تكرار إلى ما لا نهاية infinite
- animation-direction : ذات القيمة alternate وتعني الحركة بطريقة سلسه ذهاباً وإياباً.
- animation-fill-mode : ذات القيمة both.
تتكون الحركة في هذا المثال على مرحلتين فقط، المرحلة الأولى ( 0% ) بُعد العنصر عن الحافة السفلى لمكانة الأصلي هو صفر، وتعين ظل للزر بمقدار 5px، المرحلة الثانية، نقوم بجذب العنصر لأعلى عن مكانه الأصلي بمقدار 30px باستخدام الخاصية bottom وزيادة الظل للمقدار 50px.
مثال آخر
في المثال التالي سنقوم بإضافة تأثير التساقط على النص، ليظهر بالشكل التالي:
See the Pen animation #5 by Ashraf Reda (@ashrafreda) on CodePen.
تتكون الحركة في المثال السابق من ستة مراحل (يمكنك استخدام نفس الخصائص لأكثر من مرحلة بفصل المراحل بفاصلة):
- المرحلة الأولى (البداية from ) والمرحلة الثانية ( 15% ): تعيين درجة دوران العنصر 0 ومقدار تحريكة على المحور X جهة اليسار 0.
- المرحلة الثالثة ( 50% ) والمرحلة الرابعة ( 60% ): تعيين درجة الدوران 90deg في عكس اتجاه عقارب الساعة، ومقدار تحركه على المحور X لجهة اليسار 0.
- المرحلة الخامسة ( 85% ) والمرحلة السادسة ( النهاية to ): الإستمرار بدرجة الدوران 90deg في عكس اتجاه عقارب الساعة، ومقدار تحركه على المحور X لجهة اليسار 200px (لاحظ أن العنصر تم دورانه بمقدار ٩٠ درجة أي أنه سيتحرك للأسفل بدلاً من اليسار).
١- الخاصية animation-name
الخاصية animation-name تستخدم على الأقل مرتين، عند كتابة أكواد الحركة بإستخدام القاعدة @keyframes وعند تعيين اسم الحركة للعنصر المُراد تحريكه بإستخدام الخاصية animation-name أو الخاصية المختصرة animation.
1 2 3 4 5 6 7 | @keyframes anyname{ /* مراحل الحركة تُكتب هنا */ } .selector{ animation-name: anyname;} |
القيمة الإفتراضية لها none وهذا يعني أنه في حالة عدم تعيين إسم الحركة يسظهر العنصر بدون حركة.
مثل أسماء الكلاسس في CSS فإن إسم الحركة يجب أن يحتوي فقط على الأحرف (من a إلى z) الأرقام (من 0 إلى 9) الشرطة السفلية (_) الشرطة العادية (-) ولا يمكن أن تبدأ برقم أو شرطتين (–).
٢- الخاصية animation-duration
تماماً مثل الخاصية transition-duration تمكنك من تحديد المدة الزمنية للحركة، بالثانية s أو المللي ثانية ms
1 2 3 | .selector{ animation-duration: 0.5s;} |
القيمة الإفتراضية لها 0s وهذا يعني أن العنصر سيظهر بدون حركة.
٣- الخاصية animation-timing-function
أيضاً مثل الخاصية transition-timing-function تقوم بتحديد منحنى السرعة أو كيفية الحركة من مرحلة لآخرى، يمكنك تحديد قيمة الخاصية بواحدة من إحدى القيم المُعرفة مسبقاً ( ease, linear, ease-in, ease-out, ease-in-out, inherit ) أو بإستخدام الدالة cubic-bezier لإنشاء منحنيات مخصصة بخيارات متقدمة.
See the Pen animation #6 by Ashraf Reda (@ashrafreda) on CodePen.
القيمة الإفتراضية (في حالة عدم تعين قيمة أخرى) هي ease حيث تبدأ الحركة بسرعة بطيئة، ثم تزداد، ثم تنتهي ببطئ كما بدأت، يمكنك الإطلاع على كيفية عمل كل قيمة من القيم المُعرف مسبقاً للخاصية transition-timing-function من هنا.
يمكنك تعيين قيمة الخاصية منفرده هكذا:
1 2 3 | animation-timing-function: ease-in-out; |
أو من خلال الخاصية المختصرة animation هكذا:
1 2 3 4 | animation: [animation-name] [animation-duration] [animation-timing-function]; animation: bouncing 1s ease-in-out; |
٤- الخاصية animation-delay
تمكنك الخاصية animation-delay من تحديد متى ستبدأ الحركة (أو متى سيبدأ جزء معين من الحركة)، أي ستحدد فترة الإنتظار قبل بدء الحركة.
إذا تم تعيين قيمة موجبة ( مثلاً 2s ) سيتم الإنتظار ثانيتن قبل بدء الحركة، أي أن العنصر سيظل بدون حركة حتى إنتهاء مدة الإنتظار (2s). وإذا تم تعيين قيمة سالبة ( مثل -2s ) سيتم بدء الحركة على الفور، لكن ستبدأ بعد ثانيتن من بدء الحركة.
See the Pen animation #7 by Ashraf Reda (@ashrafreda) on CodePen.
يمنكك مشاهدة هذا المثال التطبيقي على شبكة مطورين موزيلا، وتكون صيغتها كالتالي:
1 2 3 | animation-delay: 5s; |
أو من خلال القيمة المختصر animation:
1 2 3 4 | animation: [animation-name] [animation-duration] [animation-timing-function] [animation-delay]; animation: bouncing 2s ease-in-out 3s; |
٥- الخاصية animation-iteration-count
تقوم الخاصية animation-iteration-count بتحديد عدد مرات تكرار الحركة، وتكون القيمة واحدة من التالي:
- رقم صحيح (القيمة الإفتراضية هي 1)
- القيمة infinite أي أن الحركة سيتم تكرارها إلى ما لا نهاية.
- القيمة initial لتعين القيمة الإفتراضية.
- القيمة inherit لوراثة القيمة من العنصر الأب.
See the Pen animation iteration count by Ashraf Reda (@ashrafreda) on CodePen.
وتكون الصيغة كالتالي:
1 2 3 | animation-iteration-count: 2; |
أو من خلال القيمة المختصرةanimation:
1 2 3 4 | animation: [animation-name] [animation-duration] [animation-timing-function] [animation-delay] [animation-iteration-count]; animation: bouncing 2s ease-in-out 3s 2; |
٦- الخاصية animation-direction
تحدد الخاصية animation-direction في أي ترتيب سيتم قراءة قاعدة @keyframes، وبالتالي ستحدد اتجاه الحركة:
- normal : تبدأ من 0% وتنتهي عند 100% ثم بتدأ ثانية من 0%.
- reverse : (عكس القيمة normal) تبدأ من 100% وتنتهي عند 0% ثم بتدأ ثانية من 100%.
- alternate : تبدأ من 0% متجهه إلى 100% ثم تتجه ثانية إلى 0%.
- alternate-reverse : (عكس القيمة alternate) تبدأ من 100% متجهه إلى 0% ثم تتجه ثانية إلى 100%.
دعنا نلقي نظرة على المثال التالي ليتضح الأمر جيداً:
See the Pen animation direction by Ashraf Reda (@ashrafreda) on CodePen.
وتكون الصيغة كالتالي:
1 2 3 | animation-direction: alternate; |
أو من خلال القيمة المختصرة animation:
1 2 3 4 | animation: [animation-name] [animation-duration] [animation-timing-function] [animation-delay] [animation-iteration-count] [animation-direction]; animation: bouncing 2s ease-in-out 3s 3 alternate; |
٧- الخاصية animation-fill-mode
تحدد الخاصية animation-fill-mode ماذا سيحدث قبل بداية الحركة وبعد أن تنتهي.
عندما تقوم بتعيين القاعدة @keyframes تحدد داخلها قواعد CSS لكل مرحلة من مراحل الحركة، الآن قواعد CSS هذة يمكنها الإشتباك مع التنسيق الإفتراضي للعنصر.
دعنا نتخيل أن لدينا الزر التالي:
- لونه أحمر بشكل إفتراضي.
- نقوم بتغير لونه للون الأزرق عند بداية الحركة.
- نقوم بتغير لونه للون الأخضر عند نهاية الحركة.
عند تطبيق الخاصية animation-fill-mode مع حركة الزر، يتغير لون الزر طبقاً للجدول التالي مع كل قيمة من قيم الخاصية:
إليك المثال التالي (قم بالضغط على الزر Return لإعادة تشغيل الحركة)
See the Pen animation fill mode by Ashraf Reda (@ashrafreda) on CodePen.
قارن العناصر بالجدول بالإعلى بالعناصر في المثال، ستجد أن العنصر الأول يظهر قبل بداية الحركة باللون الإفتراضي (الأحمر) ثم يتحول إلى اللون (الأزرق) عند بداية الحركة ثم يتحول إلى (الأخضر) عند نهاية الحركة ثم يعود مرةً ثانية للون الإفترضي (الأحمر) بعد نهاية الحركة.
٨- الخاصية animation-play-state
بإستخدام الخاصيةanimation-play-state يمكنك تشغيل الحركة (إذا كانت في وضع التوقف paused ) أو إيقافها مؤقتاً (إذا كانت في وضع التشغيل playing ). ولها قيمتين:
- القيمة playing : الرسوم المتحركة قيد التشغيل حالياً.
- القيمة paused : الرسوم المتحركة متوقفه مؤقتاً حالياً.
إليك المثال التالي:
See the Pen Animation Play State by Ashraf Reda (@ashrafreda) on CodePen.
عند تمرير المؤشر على الساعة، ستتوقف الساعة مؤقتاً، ثم تُعاود الدوران عند إبعاد المؤشر عن الساعة من أخر حركة توقفت عندها ( لو توقف مؤشر الثواني عند الثانية ٣٠ مثلاً، سيكمل الدوران بعد ذلك من الثانية ٣٠ أيضاً.
لاحظ كيف استخدمنا الخاصية animation-play-state لإقاف دوران عقارب الساعة في حالة مرور المؤشر على الساعة :hover
1 2 3 4 5 | .clock:hover .hand:after { animation-play-state: paused; } |
تطبيق أكثر من حركة على نفس العنصر Multiple Animations
لإضافة حركات متعدد لنفس العنصر، قم بالفصل بين الحركات المتعددة بعلامة الفصلة ( , ) مثال لذلك:
1 2 3 4 5 | #animate-me { animation: animX 4s forwards, animY 4s forwards; } |
في هذا المثال سيتم تطبيق حركتين منفصلتين في نفس الوقت:
- الحركة الأولى: إسم الحركة animX وتستغرق مدة 4s وباقي الخصائص يتم استخدام القيم الإفتراضية لها.
- الحركة الثانية: إسم الحركة animY وتستغرق مدة 4s وباقي الخصائص يتم استخدام القيم الإفتراضية لها.
See the Pen CSS Multiple Animations by Ashraf Reda (@ashrafreda) on CodePen.
ملاحظات وتوضيحات
- المتصفح Chrome : اللاحقة
-webkit-
- المتصفح Safari : اللاحقة
-webkit-
- المتصفح Firefox : اللاحقة
-moz-
- المتصفح Internet Explorer : اللاحقة
-ms-
- المتصفح Opera : اللاحقة
-o-
وتستخدم كالتالي:
1 2 3 4 5 6 7 | -webkit-animation: bouncing 4s; -moz-animation: bouncing 4s; -ms-animation: bouncing 4s; -o-animation: bouncing 4s; animation: bouncing 4s; |
هذا الموقع يوضح الخواص التي مازالت تحتاج إلى لواحق والخصائص التي أصبحت قياسية على جميع المتصفحات ويمكنك استخدامها بدون لواحق.
لاحظ أنه في حالة استخدام اللواحق مع القاعدة @keyframes ستكون صيغتها كالتالي:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | @-webkit-keyframes bouncing { 0% { transform: scale(0.1); } 100% { transform: scale(1); } } @keyframes bouncing { 0% { transform: scale(0.1); } 100% { transform: scale(1); } } |