DEV Community

Cover image for Animate display: none in Pure CSS! Modern @starting-style & allow-discrete Explained
Muneeb Ali
Muneeb Ali

Posted on

Animate display: none in Pure CSS! Modern @starting-style & allow-discrete Explained

For over 10 years, transitioning elements from display: none was considered impossible in pure CSS without JavaScript reflow workarounds like requestAnimationFrame or void element.offsetWidth.

Those days are officially over! Modern CSS introduces two game-changing features (Baseline 2024 across Chrome, Safari, and Firefox):

  1. @starting-style: Defines the before-change style snapshot at frame 0 when an element transitions from display: none or mounts to the DOM.
  2. transition-behavior: allow-discrete: Delays flipping to display: none until your exit transitions finish completely.


💡 The Mental Model: The Broadway Stage Analogy

To understand why this is necessary, think of a browser render engine like a Broadway theater:

  • Without @starting-style: Toggling display: none to display: block is like an actor suddenly teleporting from backstage straight into a 100% bright spotlight. The browser cannot interpolate between "does not exist in the render tree" and "fully visible", so it abruptly snaps.
  • With @starting-style: @starting-style places the actor on their backstage floor tape mark in the dark (opacity: 0, scale: 0.85) before the curtains open. Once the stage lights go up, they smoothly fade and scale into center stage.
  • With allow-discrete: When closing, allow-discrete acts like a curtain timer. It lets the exit fade play out completely before turning off the lights and sending the element backstage.

🚀 3 Real-World Production Patterns

Pattern 1: Dropdown Menus & Modals (display: none → flex)

.modal {
  display: flex;
  opacity: 1;
  transform: translateY(0);
  transition: 
    opacity 0.35s ease, 
    transform 0.35s ease, 
    display 0.35s allow-discrete;

  /* Frame 0 snapshot when switching from display: none */
  @starting-style {
    opacity: 0;
    transform: translateY(-12px);
  }
}

.modal.is-closed {
  display: none;
  opacity: 0;
  transform: translateY(-12px);
}
Enter fullscreen mode Exit fullscreen mode

Pattern 2: Native HTML5 <dialog> and ::backdrop Transitions

You can animate the native <dialog> element and its top-layer ::backdrop with zero JavaScript wrapper elements:

dialog {
  opacity: 1;
  transform: scale(1);
  transition: 
    opacity 0.3s ease, 
    transform 0.3s ease, 
    overlay 0.3s allow-discrete, 
    display 0.3s allow-discrete;

  &::backdrop {
    background-color: rgba(0, 0, 0, 0.65);
    transition: background-color 0.3s ease, display 0.3s allow-discrete;
  }
}

@starting-style {
  dialog[open] {
    opacity: 0;
    transform: scale(0.92);

    &::backdrop {
      background-color: transparent;
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Pattern 3: Dynamic DOM Elements & Toast Notifications

When appending elements dynamically with JavaScript (element.appendChild), modern CSS allows them to animate on first paint automatically:

.toast {
  opacity: 1;
  transform: translateX(0);
  transition: opacity 0.4s ease, transform 0.4s ease;

  @starting-style {
    opacity: 0;
    transform: translateX(40px);
  }
}
Enter fullscreen mode Exit fullscreen mode

🌐 Browser Compatibility (Baseline 2024)

Both @starting-style and transition-behavior: allow-discrete are part of Baseline 2024 Widely Available:

Browser Supported Version
Chrome / Edge 117+ ✅
Safari 17.5+ ✅
Firefox 129+ ✅

For older browser fallbacks, use @supports:

@supports (transition-behavior: allow-discrete) {
  /* Enhanced modern transitions */
}
Enter fullscreen mode Exit fullscreen mode

🎯 60-Second Viewer Coding Challenge

How would you make a modal scale in from 90% (0.9 → 1.0) on open, but slide down 20px as it closes?

  1. Grab the spoiler-free starter HTML from our GitHub Code Vault.
  2. Write your pure CSS solution (zero JS reflow hacks!).
  3. Drop your solution in the YouTube video comments — the top 3 best solutions will be pinned and inducted into our Community Hall of Fame! 🏆

📦 Resources & Links

Top comments (0)