Gaurav Shukla's avatar
AboutArticlesProjectsBookmarksContact
AboutArticlesProjectsBookmarksContact
February 8, 2026

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

  • HTML
  • CSS
  • Modern CSS features

Learn how to transition display: none in CSS using modern features like transition-behavior: allow-discrete and @starting-style. This article 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:

  • transition discrete properties like display
  • define a starting state when an element becomes visible

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:

Your browser does not support the video tag.

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

  • transition-behavior: allow-discrete;
  • @starting-style {}

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:

  • @starting-style applies only when the element enters
  • You should not set display inside it

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:

  • Transitioning to and from display none is easy now!
  • We can now transition to and from display: none

Documentation:

  • MDN: transition-behavior
  • MDN: @starting-style

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

Thanks for reading!

Built with love by Gaurav Shukla