CSS @keyframes and Animation Shorthands Explained
CSS animations let you move, fade, resize, and otherwise change elements over time without writing script. This article explains how @keyframes defines the animation itself and how the animation shorthand controls timing, repetition, and playback.
Quick answer: Use @keyframes to describe the animation steps, then apply it with animation-name or the animation shorthand. The shorthand can set duration, timing function, delay, iteration count, direction, fill mode, and play state in one declaration.
Difficulty: Beginner
You’ll understand this better if you know: basic CSS selectors, how declarations work, and the difference between a class and a property value.
1. What Is CSS @keyframes and Animation Shorthands?
@keyframes is the CSS rule that defines the stages of an animation. The animation shorthand is the compact way to apply that animation to an element.
- @keyframes describes what changes at specific points in time.
- animation tells the browser how to run those keyframes.
- Together, they create smooth visual changes over time.
- Animations can repeat, reverse, pause, and keep their final state.
2. Why CSS Animations Matter
Animations help users notice important changes, understand state transitions, and make interfaces feel responsive. Common examples include loading spinners, alert attention states, success feedback, and subtle onboarding motion.
They matter because they can improve clarity when used well, but they can also distract if they are too flashy or too frequent. CSS animations are especially useful for changes that happen automatically or repeatedly.
3. Basic Syntax or Core Idea
The core pattern is simple: define the keyframes, then assign them to an element.
Defining keyframes
@keyframes pulse {
from {
transform: scale(1);
}
to {
transform: scale(1.1);
}
}This animation changes an element’s scale from normal size to slightly larger.
Applying the animation with the shorthand
.card {
animation: pulse 1s ease-in-out infinite alternate;
}In this example, the element uses the pulse keyframes, runs for one second, eases in and out, repeats forever, and alternates direction each time.
How the shorthand is interpreted
- The first matching name is usually the animation name.
- Time values represent duration and delay.
- Keywords such as infinite, alternate, and paused control playback behavior.
- You can still write each longhand property separately when clarity matters.
4. Step-by-Step Examples
Example 1: A fade-in animation
This is the simplest practical animation: start invisible, then become fully visible.
@keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
.message {
animation: fadeIn 300ms ease-out 1 both;
}This fades the element in once and keeps the ending value because of both.
Example 2: Moving an element across the page
Transforms are a common animation target because they are smooth and predictable.
@keyframes slideRight {
from {
transform: translateX(0);
}
to {
transform: translateX(200px);
}
}
.banner {
animation: slideRight 2s linear 1 forwards;
}The element moves from its original position to the right and stays there after the animation ends.
Example 3: Bouncing attention state
Repeated motion often uses infinite and alternate to create a back-and-forth loop.
@keyframes bounce {
0% {
transform: translateY(0);
}
50% {
transform: translateY(-12px);
}
100% {
transform: translateY(0);
}
}
.indicator {
animation: bounce 800ms ease-in-out infinite;
}This creates a repeating motion that can draw attention to a live status or notification.
Example 4: Delayed entrance animation
Delays are useful when you want motion to start after the page is already visible.
@keyframes riseUp {
from {
opacity: 0;
transform: translateY(20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.panel {
animation: riseUp 400ms ease-out 150ms 1 both;
}The delay waits before starting, and both keeps the element hidden during the delay and visible after completion.
5. Practical Use Cases
- Fade in notifications when new content appears.
- Pulse a call-to-action button without making the page feel chaotic.
- Animate a tooltip or modal as it enters and leaves.
- Show a loading indicator while data is being fetched.
- Highlight validation feedback after a form field changes state.
- Create staggered list entrances for dashboards or onboarding screens.
6. Common Mistakes
Mistake 1: Using the animation name without defining @keyframes
An animation name in the shorthand does nothing unless a matching @keyframes rule exists. Beginners often write the property and expect motion without defining the actual steps.
Problem: The browser cannot animate because it has no keyframe rule to follow, so the element stays unchanged.
.box {
animation: spin 1s linear infinite;
}Fix: Define the named keyframes before using the shorthand.
@keyframes spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
.box {
animation: spin 1s linear infinite;
}The corrected version works because the browser now knows the start and end states to interpolate.
Mistake 2: Forgetting the duration in the shorthand
If you omit the duration, the animation usually becomes effectively invisible. The shorthand can still be syntactically valid, but the motion may run with the default duration of zero seconds.
Problem: The animation has no visible time span, so it appears not to work even though the name is correct.
.notice {
animation: fadeIn ease-out 1 both;
}Fix: Include an explicit duration, usually right after the animation name.
.notice {
animation: fadeIn 250ms ease-out 1 both;
}The fixed version animates because the browser now has a real time span to interpolate over.
Mistake 3: Expecting the final state without fill mode
By default, an animation returns the element to its original styles after it ends. Many developers expect the ending keyframe to remain visible, but that only happens when you use the right fill mode.
Problem: The animation finishes, then the element snaps back to its pre-animation style because fill-mode is not set.
@keyframes dropIn {
from {
opacity: 0;
transform: translateY(-10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.toast {
animation: dropIn 300ms ease-out 1;
}Fix: Use forwards or both when you want the final keyframe to stay applied after the animation ends.
.toast {
animation: dropIn 300ms ease-out 1 forwards;
}The corrected version keeps the ending styles, so the element does not jump back unexpectedly.
7. Best Practices
Prefer transform and opacity for smooth motion
Browsers usually animate transform and opacity more efficiently than layout-affecting properties like width or top.
@keyframes fadeLift {
from {
opacity: 0;
transform: translateY(12px);
}
to {
opacity: 1;
transform: translateY(0);
}
}This approach reduces layout work and tends to feel smoother.
Use the shorthand only when it improves readability
The shorthand is convenient, but very long values can become hard to scan. If a declaration is getting crowded, longhand properties may be clearer.
.modal {
animation-name: fadeIn;
animation-duration: 200ms;
animation-timing-function: ease-out;
animation-fill-mode: forwards;
}This version makes each setting explicit, which helps when maintaining larger stylesheets.
Respect reduced-motion preferences
Animations should not overwhelm users who prefer less motion. Use the media query to provide a calmer experience.
@media (prefers-reduced-motion: reduce) {
.card {
animation: none;
}
}This keeps the interface accessible without removing the feature for everyone.
8. Limitations and Edge Cases
- @keyframes cannot animate everything equally well. Some properties trigger layout or paint work and may feel less smooth.
- If two animations target the same property, the later one in the cascade can override the earlier result.
- Animations do not begin until the element has the animation property applied; hidden elements or removed nodes cannot visibly animate.
- Repeated animations can be distracting, especially if they run forever on large parts of the UI.
- Browser support is broad for standard CSS animations, but older or unusual environments may require prefixed code in legacy projects.
- If an animation seems to do nothing, check the animation name, duration, and whether another rule is overriding the same property.
9. Practical Mini Project
Here is a small notification card that fades and rises into view using one keyframes rule and one shorthand declaration.
.notification {
max-width: 320px;
padding: 1rem;
border-radius: 0.75rem;
background: #1f2937;
color: #fff;
animation: toastIn 280ms ease-out 1 both;
}
@keyframes toastIn {
from {
opacity: 0;
transform: translateY(16px);
}
to {
opacity: 1;
transform: translateY(0);
}
}This project demonstrates the full workflow: define a named animation, then apply it with timing, iteration, and fill behavior in one place.
10. Key Points
- @keyframes defines what changes during the animation.
- animation shorthand applies the animation and can set most related properties at once.
- Duration is essential; without it, the animation may appear broken or invisible.
- forwards and both are important when you want the final state to remain.
- transform and opacity are usually the safest properties to animate.
- Accessibility matters: provide reduced-motion alternatives when animations are noticeable.
11. Practice Exercise
- Create a @keyframes rule called highlight that changes an element’s background color from pale yellow to white.
- Apply it to a notice element using the animation shorthand.
- Make the animation run once, last half a second, and keep the final state.
Expected output: The notice briefly highlights, then remains white after the animation ends.
Hint: You will need a duration, a fill mode, and a matching animation name.
@keyframes highlight {
from {
background-color: #fef3c7;
}
to {
background-color: #ffffff;
}
}
.notice {
animation: highlight 500ms ease-out 1 forwards;
}12. Final Summary
CSS @keyframes gives you the timeline of an animation, while the animation shorthand lets you apply that timeline with duration, easing, delay, direction, repetition, and fill behavior. Once you understand how those pieces fit together, most CSS animation work becomes a matter of choosing the right values rather than learning a new syntax.
For everyday UI work, start with simple fade and transform animations, keep motion purposeful, and use fill modes intentionally. If you want to go further, the next topic to study is how the individual animation longhands map back to the shorthand and how transitions differ from animations in CSS.