This example demonstrates how display and content-visibility can be transitioned. This behavior is useful for creating entry/exit animations where you want to for example remove a container from the DOM with display: none, but have it fade out with opacity rather than disappearing immediately.
Supporting browsers transition display and content-visibility with a variation on the discrete animation type. This generally means that properties will flip between two values 50% through animating between the two.
There is an exception, however, which is when animating to/from display: none or content-visibility: hidden. In this case, the browser will flip between the two values so that the transitioned content is shown for the entire animation duration.
So for example:
- When animating
display from none to block (or another visible display value), the value will flip to block at 0% of the animation duration so it is visible throughout. - When animating
display from block (or another visible display value) to none, the value will flip to none at 100% of the animation duration so it is visible throughout.
When transitioning these properties transition-behavior: allow-discrete needs to be set on the transitions. This effectively enables display/content-visibility transitions.
When transitioning display, @starting-style is needed to provide a set of starting values for properties set on an element that you want to transition from when the element receives its first style update. This is needed to avoid unexpected behavior. By default, CSS transitions are not triggered on elements' first style updates when they first appear in the DOM, which includes when display changes from none to another state. content-visibility animations do not need starting values specified in a @starting-style block. This is because content-visibility doesn't hide an element from the DOM like display does: it just skips rendering the element's content.
HTML
The HTML contains two <p> elements with a <div> in between that we will animate from display none to block.
<p>
Click anywhere on the screen or press any key to toggle the
<code><div></code> between hidden and showing.
</p>
<div>
This is a <code><div></code> element that transitions between
<code>display: none; opacity: 0</code> and
<code>display: block; opacity: 1</code>. Neat, huh?
</div>
<p>
This is another paragraph to show that <code>display: none;</code> is being
applied and removed on the above <code><div> </code>. If only its
<code>opacity</code> was being changed, it would always take up the space in
the DOM.
</p>
CSS
html {
height: 100vh;
}
div {
font-size: 1.6rem;
padding: 20px;
border: 3px solid red;
border-radius: 20px;
width: 480px;
display: none;
opacity: 0;
transition:
opacity 1s,
display 1s allow-discrete;
/* Equivalent to
transition: all 1s allow-discrete; */
}
.showing {
opacity: 1;
display: block;
}
@starting-style {
.showing {
opacity: 0;
}
}
Note the @starting-style block used to specify the starting style for the transition, and the inclusion of the display property in the transitions list, with allow-discrete set on it.
JavaScript
Finally, we include a bit of JavaScript to set up event listeners to trigger the transition (via the showing class).
const divElem = document.querySelector("div");
const htmlElem = document.querySelector(":root");
htmlElem.addEventListener("click", showHide);
document.addEventListener("keydown", showHide);
function showHide() {
divElem.classList.toggle("showing");
}
Result
The code renders as follows: