How to transition from display: none in CSS (Finally!)

February 8, 2026

Learn how to transition display: none in CSS using modern features like transition-behavior: allow-discrete and @starting-style. this post explains why traditional transitions fail and shows how to animate elements smoothly as a progressive enhancement.

How to transition from display: none in CSS (Finally!)

Discrete properties like display and visibility could not be transitioned in CSS, until recently.

Traditionally, when an element had display: none, it was removed from the render tree. Because of that, no CSS transition (like transform or opacity) could run when the element appeared or disappeared.

That limitation is now addressed using two modern CSS features.

  1. transition-behavior: allow-discrete;
  2. @starting-style {}

Together, they allow CSS to:

The goal

We want to animate a sidebar when toggling it from:

display: none;

to:

display: grid;

…and have the transform transition work as well.

Just like this:

Consider this HTML

<button onclick="toggleSidebar()">Toggle Sidebar</button>

<aside>
  <a href="#">Home</a>
  <a href="#">About</a>
  <a href="#">Services</a>
  <a href="#">Contact</a>
</aside>

The problem with the usual approach

aside {
  transform: translateX(100%);
  display: none;
  transition: transform 150ms;
}

aside.open {
  transform: translateX(0%);
  display: grid;
}

This does not work.

Why? Because when display: none is applied, the element does not exist in the render tree, so no transition can occur.

The solution: using modern CSS features

Step 1: Allow discrete transitions

Set transition-behavior: allow-discrete and ensure display is included in transition-property.

aside {
  transform: translateX(100%);
  display: none;

  /* Step 1: Allow discrete transitions */
  transition-behavior: allow-discrete;

  /* Include display explicitly */
  transition-property: transform, display;
  transition-duration: 150ms;
}

Step 2: Define the starting styles

Use @starting-style to define how the element should look right before it becomes visible.

@starting-style {
  aside.open {
    transform: translateX(100%);
    /* Do NOT set display: none here */
  }
}

Important:

Final working code

aside {
  transform: translateX(100%);
  display: none;

  transition-behavior: allow-discrete;
  transition-property: transform, display;
  transition-duration: 150ms;
}

aside.open {
  transform: translateX(0%);
  display: grid;
}

@starting-style {
  aside.open {
    transform: translateX(100%);
  }
}

That’s it!

Now the sidebar transitions smoothly from display: none to grid, along with the transform animation.

Live demo

See the Pen Transition from display none by heygauravshukla (@heygauravshukla) on CodePen.

Caveat: Browser support

This works in all modern browsers.

In Firefox, the transition currently works only when entering (for example, display: none → grid), but not when exiting.

Because of this, the technique is best used as a progressive enhancement.

References & further reading

The inspiration for this post came from Kevin Powell’s excellent content:

Documentation:

Even with its current Firefox limitation, this approach is a clean and practical progressive enhancement for modern UI components.

Thanks for reading!