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
display
property 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
display
andcontent-visibility
on a keyframe timeline (Chrome 116+) - The
transition-behavior
property with theallow-discrete
keyword (Chrome 117+) - The
@starting-style
rule for entry animations (Chrome 117+) - The
overlay
property 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.