How to Fix Issues With CSS "transition" Property Not Working?

There could be a number of reasons why the CSS transition property might not be working for you. You can check the following list of things to fix some common/potential issues with using it:

  1. Check for Browser Compatibility;
  2. Validate the Syntax;
  3. Validate the Value;
  4. Check for Unsupported Properties;
  5. Check the Animatable Types for the Property;
  6. Validate the Start and End Values;
  7. Check the Transition Delay Value;
  8. Check if Element State Was Changed;
  9. Check for Overriding Rules.

Checking for Browser Compatibility

The CSS transition property has great browser support. However, before you check for other issues, it might be a good idea to ensure that you're using a browser that supports the CSS transition property.

Some older versions of browsers may require vendor prefixes for the transition property to work. If these prefixes are not included, the transition may not work as expected. Following is a list of all the vendor prefixes for the transition property:

-webkit-transition: ...; /* Chrome < 26, Safari < 9 */
-moz-transition: ...; /* Firefox < 16 */
-o-transition: ...; /* Opera < 12.10 */
transition: ...; /* IE10+, Firefox 16+, Chrome 26+, Opera 12.10+ */

If you wish to support old browsers that require vendor prefixes, then you may also want to check if the property you wish to add transition to requires a vendor prefix as well. For example, the CSS transform property requires vendor prefixes for some older browsers.

Validating the Syntax

The transition property can be specified as one or more single-property transitions, for example, like the following:

/* apply transition to 1 property */
transition: opacity 2s;

/* apply transition to 2 properties */
transition: opacity 2s, color 4s 2s;

/* apply transition to all changed properties */
transition: all 2s;

Each single-property transition can have any one of the following syntax:

transition: property-name duration;

transition: property-name duration easing-function;

transition: property-name duration delay;

transition: property-name duration easing-function delay;

It might be a good idea to make sure you're using the right syntax before you dig deeper.

Validating the Value

The CSS transition property is actually a shorthand for the following properties:

You should make sure that you're specifying the correct value for whichever one of them you use.

transition-property

Make sure that the value you are using for the transition-property property, in the transition shorthand syntax, is valid — i.e. one of the following:

transition: all /* ... */;
transition: none /* ... */;
transition: <property-name> /* ... */; /* e.g. transition: opacity, color, ... */
/* global values */
transition: inherit /* ... */;
transition: initial /* ... */;
transition: revert /* ... */;
transition: revert-layer /* ... */;
transition: unset /* ... */;

Please note that the transition property only works with animatable properties.

transition-duration

Make sure that the value you are using to define the transition-duration, in the transition shorthand syntax, is valid CSS <time> value — i.e. a number followed by s (for seconds) or ms (for milliseconds).

Other than that, you can also specify any of the following global values, that are inherited:

/* global values */
transition: /* ... */ inherit;
transition: /* ... */ initial;
transition: /* ... */ revert;
transition: /* ... */ revert-layer;
transition: /* ... */ unset;

transition-timing-function

Make sure that the value you are using for the transition-timing-function property, in the transition shorthand syntax, is valid — i.e. one of the following:

/* keyword values */
transition: /* ... */ ease;
transition: /* ... */ ease-in;
transition: /* ... */ ease-out;
transition: /* ... */ ease-in-out;
transition: /* ... */ linear;
transition: /* ... */ step-start;
transition: /* ... */ step-end;
/* function values */
transition: /* ... */ steps(4, jump-end);
transition: /* ... */ cubic-bezier(0.1, 0.7, 1, 0.1);
/* global values */
transition: /* ... */ inherit;
transition: /* ... */ initial;
transition: /* ... */ revert;
transition: /* ... */ revert-layer;
transition: /* ... */ unset;

transition-delay

Make sure that the value you are using to define the transition-delay, in the transition shorthand syntax, is valid CSS <time> value — i.e. a number (that's either 0, negative or positive) followed by s (for seconds) or ms (for milliseconds).

Other than that, it also inherits the following global values:

/* global values */
transition: /* ... */ inherit;
transition: /* ... */ initial;
transition: /* ... */ revert;
transition: /* ... */ revert-layer;
transition: /* ... */ unset;

Checking for Unsupported Properties

The transition property only works with animatable properties. This means that some properties, such as the CSS display property, cannot be animated/transitioned.

If this is causing the issue for you, then you can simply use an animatable property to create the transition effect you are trying to achieve with the non-animatable property. For example, a good substitute for creating the fade-in effect could be to use the CSS opacity property instead of display.

Checking the Animatable Types for the Property

"Animatable type" is a term that refers to the type of values that can be used with an animatable CSS property.

Each animatable property in CSS has a set of animatable value types, which are the values that can be used to create a transition between the starting and ending states of the property. You can find the "animatable type" of animatable properties in their respective specification document (or formal definition) on MDN, W3, etc.

For example, the animation value type of the CSS height property is defined as the following:

This means that if you try to transition the height property to/from any other value than these, it will not work. This is the same reason why you cannot transition to/from "height: auto", as it's not a valid animation type for the height property.

Validating the Start and End Values

Transitions happen between two states — i.e. from a start value to an end value. Therefore, you can make sure of the following:

  1. An initial and final state for the property you're trying to transition is defined;
  2. The initial and final state values are not the same as each other;
  3. Both, the initial and final state values exist.

For example, consider the following HTML/CSS:

<div class="box">Foo</div>
.box {
  /* opacity: 0.2; */
  transition: opacity 1s ease;
}

.box:hover {
  opacity: 1;
}

This does not work as expected because the initial state is not defined (it's commented out), making it default to "opacity: 1". This means that the initial state is the same as the final state, and there's nothing to transition to.

For this to work, you need to define a value for the initial state that's different from the final state value:

.box {
  opacity: 0.2;
  transition: opacity 1s ease;
}

.box:hover {
  opacity: 1;
}

Checking the Transition Delay Value

Transition delay can be defined as 0, or a negative or positive value, which all have a different meaning:

  • 0 — starts the transition effect immediately;
  • Negative value — starts the transition effect immediately, starting from the given length of time;
  • Positive value — delays the start of the transition effect by the given length of time.

Therefore, if your style rule has a delay specified, it might be a good idea to check if you have the correct value to prevent unexpected behavior.

Checking if Element State Was Changed

For a transition effect to take place, the state of the element has to be changed in some way. This can happen either programmatically (i.e. through a script or code that modifies the element's properties), or through some user interaction, such as hovering over the element or clicking a button.

For example, it could be that the user hovers over the element, and based on that interaction you want to transition to a different state for a specific CSS property.

Without a change in the element's state, there is nothing for the transition to animate between, and for that reason the transition will not have any effect.

To fix such an issue, you just need to make sure that the transition is happening when the state of the element changes in some way.

Checking for Overriding Rules

It could be that the element you are applying the transition property to is being overridden by a more specific selector.

For example, consider the following HTML/CSS:

<div id="parent">
  <div class="box">Foo</div>
  <!-- ... -->
</div>
.box {
  opacity: 0.2;
  transition: opacity 2s;
}

.box:hover {
  opacity: 1;
}

It could be the case, for example, that another CSS selector with higher specificity is overriding your selector and changing the transition property on the element, as shown in the example below:

#parent .box {
  transition: none;
}

In this case, the selector "#parent .box" has a higher specificity than ".box", which means that it will set the value of the transition property to none.

To fix this, you can either remove the more specific selector, or make your selector more specific than the other one.

Other than that, it could also be that one of the following transition-* properties are defined on the same element, overriding the style rule defined by your transition property:

An example of this could be, for example, when one of the transition-* properties overrides the style rule defined in the same CSS selector:

.box {
  opacity: 0.2;
  transition: opacity 2s;
  /* ... */
  transition-delay: 2s;
}

.box:hover {
  opacity: 1;
}

In this example, the transition would start with a delay of 2s, leading to potentially unexpected behavior. Another example could be where similar kind of thing happens, but in a selector with higher specificity:

.box {
  opacity: 0.2;
  transition: opacity 2s;
}
#parent .box {
  transition-delay: 2s;
}

Other possibilities of style rules with a higher specificity could be the ones having the !important keyword, or an overriding transition property that's added via the HTML element's style attribute.


This post was published by Daniyal Hamid. Daniyal currently works as the Head of Engineering in Germany and has 20+ years of experience in software engineering, design and marketing. Please show your love and support by sharing this post.