حركة CSS في مثال واحد
للحركة جزءان: @keyframes، التي تصف الخطوات، والخاصية animation، التي تطبّقها على عنصر مع مدة. تنزلق هذه البطاقة وتظهر تدريجيًا عند تحميل الصفحة:
عدّل الشيفرة (أو غيّر المدة إلى 2s) فتُعاد المعاينة، وتستطيع مشاهدة البطاقة تدخل مرة أخرى. تستبدل كتلة @media (prefers-reduced-motion: reduce) الإطارات المفتاحية بتلاشٍ فقط للقراء الذين ضبطوا أنظمتهم على تقليل الحركة.
صيغة @keyframes
@keyframes pulse {
0% { transform: scale(1); }
50% { transform: scale(1.08); }
100% { transform: scale(1); }
}
fromهي نفسها0%، وtoهي نفسها100%.- أضف من الخطوات المئوية ما تحتاج. الخطوات ذات الأنماط نفسها يمكن أن تشترك في سطر:
0%, 100% { ... }. - الخاصية الغائبة عن الإطار المفتاحي الأول أو الأخير تُحرَّك من قيمة العنصر نفسه أو إليها.
- الاسم (
pulse) هو ما تمرره إلىanimation-name. حساس لحالة الأحرف ويجب ألا يكون كلمة مفتاحية مثلnone.
خصائص animation
| الخاصية | ما تضبطه | الافتراضي |
|---|---|---|
animation-name | أي @keyframes تُشغَّل | none |
animation-duration | طول الدورة الواحدة | 0s |
animation-timing-function | منحنى السرعة بين الإطارات المفتاحية | ease |
animation-delay | الانتظار قبل الدورة الأولى (القيمة السالبة تبدأ من منتصف الطريق) | 0s |
animation-iteration-count | عدد الدورات، أو infinite | 1 |
animation-direction | normal، reverse، alternate، alternate-reverse | normal |
animation-fill-mode | الأنماط قبل الحركة وبعدها: none، forwards، backwards، both | none |
animation-play-state | running أو paused | running |
يقبلها الاختصار بأي ترتيب تقريبًا. القاعدة الوحيدة أن قيمة الزمن الأولى هي المدة والثانية هي التأخير:
.loader {
animation: pulse 1.2s ease-in-out 0.2s infinite alternate both;
/* name duration timing delay count direction fill */
}
direction وfill-mode مباشرة
اختر اتجاهًا ونمط تعبئة وعددًا، ثم اضغط Play. يتحرك الصندوق 200px إلى نهاية المسار. وتخبرك القراءة أين استقر بعد انتهاء الحركة:
ما يجب ملاحظته:
fill-mode: none(الافتراضي): بعد الإطار الأخير يقفز الصندوق عائدًا إلىx = 0ويعود كهرمانيًا.forwards: يبقى على الإطار المفتاحي الأخير. معnormalيكون ذلكx = 200وأخضر؛ ومعreverseينتهي عندx = 0وأزرق، لأن الإطار المفتاحي الأخير الذي شُغّل هوfrom.alternateمع عدد 2 يذهب ويعود، فحتىforwardsتنتهي عندx = 0.
حلقات لا نهائية: مؤشر تحميل
تكرر infinite بلا توقف، وanimation-delay على كل ابن تزيحها كي تتحرك بالتناوب. اجعل الحلقات هادئة: بطيئة، وصغيرة، وبلا وميض.
تخبر role="status" مع aria-label مستخدمي قارئات الشاشة بأن شيئًا ما قيد التحميل، وهو ما لا تقوله النقاط وحدها. للدائرة الدوارة راجع صفحة rotate.
الإيقاف المؤقت والتحكم في الحركات
تجمّد animation-play-state: paused الحركة حيث هي، وrunning تكملها من هناك. مرّر المؤشر فوق الشريط أدناه لإيقافه مؤقتًا:
من JavaScript تعيد element.getAnimations() حركات CSS الجارية، ولكل منها pause() وplay() وcancel() وcurrentTime تستطيع قراءتها أو ضبطها. يُطلق الحدث animationend حين تنتهي حركة غير لا نهائية، وanimationiteration في نهاية كل دورة.
احترم تقليل الحركة ولا تستخدم الوميض أبدًا
قاعدتان لسهولة الوصول تنطبقان على كل حركة:
- تقليل الحركة. يمكن للناس أن يطلبوا من أنظمتهم حركة أقل لأن الحركة تُتعبهم. النمط الأكثر أمانًا أن تضيف الحركة فقط حين لا يطلبون تقليلها:
@media (prefers-reduced-motion: no-preference) {
.hero-title { animation: slide-in 0.8s ease-out both; }
}
- لا وميض. المحتوى الذي يومض أكثر من ثلاث مرات في ثانية واحدة قد يسبب نوبات صرع. تجنب الوميض السريع عالي التباين تمامًا.
اجعل الحركات سلسة
حرّك transform وopacity حين تستطيع. يستطيع المتصفح تطبيقهما من دون إعادة ترتيب الصفحة، فتبقيان سلستين حتى على الهواتف البطيئة. تحريك width أو height أو top أو left أو margin يعيد حساب التخطيط في كل إطار. لتحريك عنصر استخدم translate() من صفحة transform.
أخطاء شائعة
- لا مدة. لا تفعل
animation: fade;شيئًا، لأن المدة الافتراضية0s. - اسم غير مطابق. يجب أن يطابق
animation-nameاسم@keyframesتمامًا، بما في ذلك حالة الأحرف. - القفز عائدًا في النهاية. أضف
forwards(أوboth) للاحتفاظ بالإطار المفتاحي الأخير. - وميض قبل بدء حركة مؤجلة. أثناء
animation-delayيُظهر العنصر أنماطه العادية. تطبّقbackwards(أوboth) الإطار المفتاحي الأول أثناء التأخير. - إعادة تشغيل حركة بضبط القيمة نفسها. ضبط
animationنفسها مرة أخرى لا يفعل شيئًا. احذفها، وافرض إعادة حساب التخطيط (el.offsetWidth)، ثم اضبطها من جديد، كما يفعل زر Play أعلاه. - تحريك
display. تتبدل فورًا. حرّكopacityوtransformبدلًا منها.
الأسئلة الشائعة
كيف أصنع حركة في CSS؟
عرّف الخطوات بـ @keyframes name { from { ... } to { ... } }، ثم طبّقها على عنصر بالخاصية animation مع مدة: animation: name 1s ease-out;. المدة مطلوبة، لأن قيمتها الافتراضية 0s.
ماذا تفعل animation-fill-mode: forwards؟
تحتفظ بأنماط الإطار المفتاحي الأخير بعد انتهاء الحركة. من دونها يقفز العنصر عائدًا إلى أنماطه العادية. تطبّق backwards الإطار المفتاحي الأول أثناء التأخير، وboth تفعل الأمرين.
كيف أجعل حركة CSS تتكرر إلى الأبد؟
اضبط animation-iteration-count: infinite، أو أضف infinite إلى الاختصار: animation: spin 1s linear infinite;. أضف alternate لتشغيلها إلى الأمام ثم إلى الخلف في كل دورة.
ما الفرق بين animation وtransition في CSS؟
يحرّك الانتقال خاصية بين قيمتين حين تتغير، عادةً عند التمرير أو تغيير فئة. أما الحركة فتعمل من تلقاء نفسها بمجرد تطبيقها، ويمكن أن تكون لها أي عدد من الإطارات المفتاحية، ويمكن أن تتكرر وتنعكس وتتوقف مؤقتًا.
كيف أوقف حركة CSS مؤقتًا؟
اضبط animation-play-state: paused على العنصر، مثلًا عند :hover أو عبر فئة يضيفها JavaScript. وإعادتها إلى running تكمل الحركة من حيث توقفت.
كيف أوقف الحركات للمستخدمين الذين يفضلون تقليل الحركة؟
أحط الحركة بـ @media (prefers-reduced-motion: no-preference) { ... }، أو احذفها داخل @media (prefers-reduced-motion: reduce) { ... }. يتبع الاستعلام إعداد تقليل الحركة في نظام تشغيل المستخدم.