Animating elements from display: none to display: block has long been a challenge in CSS. The traditional display property doesn't support transitions, making smooth animations difficult. However, with the introduction of the @starting-style at-rule and other new CSS features, we now have powerful tools to create seamless transitions between these states.
The Challenge with display: none
Traditionally, animating an element from display: none to display: block wasn't possible because:
- The
displayproperty is not animatable. - When an element is
display: none, it's removed from the document flow, making it impossible to transition its properties.
New CSS Features for Smooth Animations
Chrome 116 and 117 introduced four new web platform features that enable smooth animations and transitions for discrete properties:
- Animating
displayandcontent-visibilityon a keyframe timeline (Chrome 116+) - The
transition-behaviorproperty with theallow-discretekeyword (Chrome 117+) - The
@starting-stylerule for entry animations (Chrome 117+) - The
overlayproperty to control top-layer behavior during animations (Chrome 117+)
Let's explore these features in detail.
Animating display in Keyframes
From Chrome 116, you can use display and content-visibility in keyframe rules. Here's an example:
.card {
animation: fade-out 0.5s forwards;
}
@keyframes fade-out {
100% {
opacity: 0;
display: none;
}
}
This animation fades out the element and sets it to display: none at the end.
The transition-behavior Property
To transition discrete properties like display, use the allow-discrete mode of the transition-behavior property:
.card {
transition:
opacity 0.25s,
display 0.25s;
transition-behavior: allow-discrete;
}
.card.fade-out {
opacity: 0;
display: none;
}
The @starting-style Rule for Entry Animations
The @starting-style rule allows you to define the initial state for entry animations:
@starting-style {
.item {
opacity: 0;
height: 0;
}
}
.item {
height: 3rem;
display: grid;
overflow: hidden;
transition:
opacity 0.5s,
transform 0.5s,
height 0.5s,
display 0.5s allow-discrete;
}
This setup creates a smooth entry animation from height: 0 and opacity: 0 to the final state.
Animating Elements to and from the Top Layer
For elements like dialogs and popovers that use the top layer, you can use @starting-style and the overlay property for smooth animations:
@starting-style {
dialog[open] {
translate: 0 100vh;
}
}
dialog[open] {
translate: 0 0;
}
dialog {
transition:
translate 0.7s ease-out,
overlay 0.7s ease-out allow-discrete,
display 0.7s ease-out allow-discrete;
translate: 0 100vh;
}
The overlay property ensures that the element stays in the top layer during the animation, preventing it from being clipped or covered by other elements.
CodePen Example
Here's a CodePen demonstrating these techniques:
CodePen: Animate from display: none using @starting-style
Browser Support
As of 2024, these features are supported in most modern browsers, including Chrome, Edge, and Firefox. However, it's always a good idea to check Can I use for the latest browser support information.
Fallback for Older Browsers
For browsers that don't support these new features, you can use a JavaScript-based fallback:
if (!CSS.supports('@starting-style {}')) {
// Fallback animation logic here
}
Conclusion
The introduction of @starting-style, transition-behavior: allow-discrete, and the overlay property provides elegant solutions to the long-standing problem of animating elements from display: none to display: block. These features allow for smooth, performant transitions without the need for complex JavaScript workarounds.