A CSS transition usually stops working when the transition is placed on the wrong state, the property cannot be animated, the starting value is missing, or another CSS rule overrides the change.
CSS Animation Fix
Why is my CSS transition not working?
A CSS transition can look broken even when the syntax seems correct. The element may jump instantly, the hover state may change without animation, the accordion may open suddenly, or the effect may work in one direction but not the other. The real cause is usually one of a few things: the transition is on the wrong selector, the property cannot animate smoothly, the browser has no starting value, or another rule is overriding the final state.
- CSS transition
- Hover animation
- Animatable properties
- Motion debugging
What the bug looks like
The element changes instantly, only animates one way, ignores the transition, or jumps when it should slide, fade, lift, or expand smoothly.
Why it happens
CSS transitions only animate between known values for animatable properties. If the property cannot interpolate, there is nothing to animate.
What usually fixes it
Put transitions on the base state, animate transform or opacity when possible, define clear start/end values, and avoid transitioning display.
The transition is only written on the hover state
This is one of the most common transition mistakes. If the transition is only declared inside :hover, the browser may animate when entering hover but snap back when leaving. The base element should know how to transition.
Broken code
Transition on hover only.card:hover {
transform: translateY(-6px);
background: #fff5ef;
transition: transform .2s ease;
}
Broken visual result
Correct code
Transition on base element.card {
transition:
transform .2s ease,
background .2s ease;
}
.card:hover {
transform: translateY(-6px);
background: #fff5ef;
}
Fixed visual result
You are trying to transition display
display:none to display:block is not a smooth animation. The element is either in the layout or not. The browser cannot gradually interpolate between those two states.
Broken code
Display cannot fade.menu {
display: none;
transition: display .2s ease;
}
.nav:hover .menu {
display: block;
}
Broken visual result
display like opacity or transform.Correct code
Opacity and transform.menu {
opacity: 0;
transform: translateY(8px);
pointer-events: none;
transition:
opacity .2s ease,
transform .2s ease;
}
.nav:hover .menu {
opacity: 1;
transform: translateY(0);
pointer-events: auto;
}
Fixed visual result
The changed property is not included in the transition
If you change transform but only transition background, the color may animate while the movement jumps instantly. The transition list has to include the property that changes.
Broken code
Wrong property listed.box {
transition: background .2s ease;
}
.box:hover {
transform: translateX(80px);
background: #ff6a3d;
}
Broken visual result
Correct code
Transition real changes.box {
transition:
transform .2s ease,
background .2s ease;
}
.box:hover {
transform: translateX(80px);
background: #ff6a3d;
}
Fixed visual result
The property causes layout jumps instead of smooth motion
Some properties can animate, but they are expensive or visually awkward because they force layout recalculation. Animating width, height, margin, or top can feel jumpy. For motion, transform is usually safer.
Broken code
Layout-heavy animation.badge {
width: 88px;
transition: width .2s ease;
}
.badge:hover {
width: 170px;
}
Broken visual result
Correct code
Transform instead.badge {
transform: scale(1);
transition: transform .2s ease;
}
.badge:hover {
transform: scale(1.08);
}
Fixed visual result
transform and opacity when they fit the design.A production-minded transition pattern
A better transition setup is intentional. It defines a stable base state, animates predictable properties, respects reduced motion preferences, and avoids layout-heavy changes unless they are truly necessary.
Premium code
Smooth and safer.card {
transform: translateY(0);
opacity: 1;
border-color: #e5e7eb;
box-shadow: 0 12px 28px rgba(15,23,42,.06);
transition:
transform .2s ease,
border-color .2s ease,
box-shadow .2s ease;
}
.card:hover,
.card:focus-within {
transform: translateY(-4px);
border-color: #ffd2c2;
box-shadow: 0 18px 38px rgba(255,106,61,.12);
}
@media (prefers-reduced-motion: reduce) {
.card {
transition: none;
}
.card:hover,
.card:focus-within {
transform: none;
}
}
Premium visual result
The card has a clear base state, a clear hover/focus state, smooth visual feedback, and a reduced-motion fallback.
Fast practical rule
If a CSS transition is not working, inspect whether the property actually changes. Then check whether that property is animatable, included in the transition list, and declared from a clear starting value on the base element.
Debug checklist
- Put
transitionon the base element, not only on:hover. - Confirm the property you are changing is included in the transition list.
- Check whether the property can actually animate smoothly.
- Avoid trying to transition
display:nonetodisplay:block. - Use
opacity,transform, ormax-heightpatterns when appropriate. - Define a clear starting value and ending value.
- Check DevTools to confirm no stronger rule overrides the hover or active state.
- Use
prefers-reduced-motionfor more respectful production UI.
Final takeaway
A CSS transition not working usually means the browser has no smooth path between two values. Either the transition is on the wrong selector, the wrong property is listed, the property cannot animate, or the final state is being overridden.
Start by proving that the property actually changes. Then make sure the base element owns the transition and the property can be interpolated. Once those pieces are correct, the transition becomes predictable instead of mysterious.