الحركة في CSS: animation و keyframes
في الدرس السابق حرّكت العناصر بـ transition، لكنها تحتاج دائماً سبباً: مرور فأرة أو تغيّر كلاس. وهي تنتقل بين حالتين فقط. ماذا عن دائرة تحميل تدور بلا توقف؟ أو عنصر يدخل الصفحة منزلقاً عند فتحها؟ هنا تحتاج animation: حركة تعمل وحدها، وتمر بأي عدد من المراحل، وتتكرر كما تشاء.
الفكرة: مشاهد ثم تشغيل
Section titled “الفكرة: مشاهد ثم تشغيل”الحركة في CSS تُبنى في خطوتين:
- تعريف المشاهد بقاعدة
@keyframes: كيف يبدو العنصر في بداية الحركة، وفي نهايتها، وربما في منتصفها. - ربط الحركة بعنصر بخاصية
animation: كم تستمر، وكم مرة تتكرر.
تخيّل دفتر الرسوم المتحركة: ترسم في صفحاته أوضاعاً مختلفة للشخصية، ثم تقلّب الصفحات بسرعة فتراها تتحرك. أنت ترسم الأوضاع الرئيسية فقط في @keyframes، والمتصفح يرسم كل ما بينها.
أول حركة
Section titled “أول حركة”@keyframes fade-in { from { opacity: 0; } to { opacity: 1; }}
.message { animation: fade-in 1s;}@keyframes fade-in: حركة سمّيناهاfade-in. الاسم من اختيارك.from: حالة البداية. وto: حالة النهاية.animation: fade-in 1s: شغّل هذه الحركة على العنصر لمدة ثانية.
النتيجة: العنصر يظهر تدريجياً عند تحميل الصفحة، بلا أي تفاعل من المستخدم.
أكثر من مرحلتين
Section titled “أكثر من مرحلتين”بدلاً من from و to اكتب نسباً مئوية من زمن الحركة:
@keyframes traffic { 0% { background: crimson; } 50% { background: gold; } 100% { background: green; }}0% تساوي from، و 100% تساوي to. وتستطيع أن تضيف أي عدد من المراحل بينهما. وإذا تشابهت مرحلتان فاجمعهما:
@keyframes pulse { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.15); }}العنصر يكبر في منتصف الحركة ثم يعود إلى حجمه، مثل نبضة قلب.
خصائص التحكم
Section titled “خصائص التحكم”| الخاصية | وظيفتها | أمثلة |
|---|---|---|
animation-name |
اسم الحركة | pulse |
animation-duration |
مدة الدورة الواحدة | 2s أو 500ms |
animation-timing-function |
منحنى السرعة | linear و ease-in-out |
animation-delay |
تأخير قبل البدء | 0.5s |
animation-iteration-count |
عدد مرات التكرار | 3 أو infinite |
animation-direction |
اتجاه التشغيل | normal و alternate |
animation-fill-mode |
حالة العنصر قبل الحركة وبعدها | forwards و both |
وتُكتب كلها غالباً في سطر واحد مختصر:
.heart { animation: pulse 1s ease-in-out infinite;}الاسم، ثم المدة، ثم المنحنى، ثم عدد المرات. والمتصفح يميّز بين القيم من نوعها. وإذا كتبت زمنين فالأول هو المدة والثاني هو التأخير.
infinite و alternate
Section titled “infinite و alternate”infinite: الحركة لا تتوقف أبداً.alternate: بعد كل دورة تنعكس الحركة، فتذهب ثم تعود بدلاً من أن تقفز إلى البداية.
@keyframes slide { from { transform: translateX(0); } to { transform: translateX(100px); }}
.ball { animation: slide 1s ease-in-out infinite alternate;}الكرة تذهب إلى اليمين ثم ترجع بنعومة، بلا توقف.
forwards: ابقَ حيث انتهيت
Section titled “forwards: ابقَ حيث انتهيت”الأصل أن العنصر يعود إلى شكله الأصلي فور انتهاء الحركة. إذا أردته أن يبقى على حالة النهاية فأضف forwards:
.toast { animation: fade-in 0.4s forwards;}مثال عملي: مؤشر التحميل
Section titled “مثال عملي: مؤشر التحميل”الدائرة التي تدور أثناء الانتظار ليست صورة. هي عنصر واحد وحركة واحدة:
.spinner { width: 40px; height: 40px; border: 4px solid #e6e8f0; border-top-color: #5b5bf0; border-radius: 50%; animation: spin 0.8s linear infinite;}
@keyframes spin { to { transform: rotate(360deg); }}إطار دائري رمادي، وجزؤه العلوي ملون، والعنصر كله يدور. لاحظ أمرين:
- كتبنا
toفقط. المتصفح يعتبر الحالة الحالية للعنصر هي البداية. - المنحنى
linear، لأن الدوران المستمر يحتاج سرعة ثابتة، وإلا بدا متقطعاً.
transition أم animation؟
Section titled “transition أم animation؟”transition |
animation |
|
|---|---|---|
| متى تبدأ؟ | عند تغيّر خاصية: hover أو كلاس |
وحدها، من لحظة ظهور العنصر |
| عدد المراحل | اثنتان: قبل وبعد | أي عدد |
| التكرار | لا | نعم، حتى بلا نهاية |
| تناسب | الاستجابة لتفاعل المستخدم | التحميل، ولفت النظر، والدخول |
احترم خيار تقليل الحركة
Section titled “احترم خيار تقليل الحركة”الحركة المستمرة تتعب بعض الناس، وقد تسبب لهم دواراً. أوقفها لمن طلب ذلك من إعدادات جهازه:
@media (prefers-reduced-motion: reduce) { .ball, .heart { animation: none; }}جرّب بنفسك
Section titled “جرّب بنفسك”غيّر مدة حركة الدائرة من 0.8s إلى 3s، واحذف كلمة alternate من حركة الكرة وشاهد القفزة. ثم أضف مرحلة 50% إلى حركة slide تغيّر فيها لون الكرة:
الناتج
أخطاء شائعة
Section titled “أخطاء شائعة”- اسم الحركة لا يطابق: الاسم بعد
@keyframesيجب أن يطابق الاسم فيanimationحرفاً بحرف، وإلا لم يحدث شيء. - نسيان المدة: المدة الافتراضية صفر، فالحركة تنتهي قبل أن تراها.
- العنصر يرجع فجأة عند النهاية: أضف
forwardsليبقى على حالة النهاية. - حركات كثيرة لا تتوقف: تشتت القارئ وتستهلك البطارية. اجعل الحركة المستمرة لمؤشرات التحميل، والباقي مرة واحدة.
اختبر نفسك
Section titled “اختبر نفسك”سؤال
ما وظيفة قاعدة @keyframes؟
@keyframes تعرّف المشاهد فقط. أما التشغيل والمدة والتكرار فتحددها خاصية animation على العنصر.
سؤال
ماذا تعني animation: bounce 2s infinite alternate؟
2s مدة الدورة، و infinite تكرار بلا توقف، و alternate تجعل الحركة تذهب ثم تعود.
الخلاصة
Section titled “الخلاصة”@keyframesتعرّف مراحل الحركة بـfromوtoأو بنسب مئوية.animationتربط الحركة بالعنصر: الاسم، والمدة، والمنحنى، وعدد المرات.infiniteللتكرار الدائم، وalternateللذهاب والعودة، وforwardsللبقاء على حالة النهاية.transitionللاستجابة لتفاعل، وanimationلحركة تعمل وحدها.- استخدم الحركة باعتدال، وأوقفها مع
prefers-reduced-motion.