Re: [csswg-drafts] [css-transitions-2] Exit animations (`@exit-style`) (#9500)

I don’t think `transition-behavior: allow-discrete` on `display` fixes anything here. It doesn’t change anything to the current workarounds, expect for the timing now being controlled by the `transition-duration` set on `display`.

See https://codepen.io/bramus/pen/azmJgLQ/d0aa5bbb528fa6c52e19a2234abc8075 for a starter demo, with these notes:

- When removing an element using the bin icons, the removal is immediate.
- If you swap out the `e.target.parentElement.remove();` by a `e.target.parentElement.style.display = 'none';` then, yes, you would get a delayed visual removal thanks to the `transition-behavior: allow-discrete` but:
  - This is not what you intended: you want the element to be _removed from the DOM_, not just hidden.
  - There still is no way to add a slide-out transition of some sorts before the element gets removed.
  - You’d still need to listen for a `transitionend` to do _the actual removal_, which was one of the points of friction listed in the OP

So I think we’re back to square one here.

---

What `transition-behavior: allow-discrete` on `display` does allow you to do though, is to have this be more backed by CSS-y bits. In https://codepen.io/bramus/pen/zxKZVjM/8ff25483b96e69e1d5d8f8aacc63243c I have a demo that uses this, but as you can see it still requires the current JavaScript-approaches as listed in the OP:

- CSS:

  ```css
  .element {
    /* Exaggerated timings */
    transition: opacity 1s ease, translate 1s ease, display 1s ease allow-discrete;
  
    &.exit-style {
      opacity: 0;
      translate: 0 -200px;   
    }
  }
  ```
- JS:
  
  ```js
  document.querySelector('.cards').addEventListener('click', e => {
    if (e.target.classList.contains('delete-btn')) {
      const $parent = e.target.parentElement;
      removeWithExitTransition($parent);
    }
  });
  
  const removeWithExitTransition = ($element) => {
    $element.classList.add('exit-style');
    $element.style.display = 'none';
    $element.addEventListener('transitionend', (e) => {
      if (e.propertyName === 'display') {
        $element.remove();
      }
    });
  }
  ```

What `@exit-style` is asking about, is to give us a CSS way to do this in just CSS, so that when calling `Element.remove()` (or setting the element to `display: none`), it would do those transitions first.

- CSS:

  ```css
  .element {
    /* Exaggerated timings */
    transition: opacity 1s ease, translate 1s ease, display 1s ease allow-discrete;
  
    @exit-style {
      opacity: 0;
      translate: 0 -200px;   
    }
  }
  ```

- JS:

  ```js
  document.querySelector('.cards').addEventListener('click', e => {
    if (e.target.classList.contains('delete-btn')) {
      const $parent = e.target.parentElement;
      $parent.remove();
  });
  ```

---

So, in summary, I think the ask is two-fold here:

- Introduce `@exit-style` to allow authors to put those styles in that rule
- When a Element gets removed or hidden, respect those `@exit-style`s

The `transition-behavior: allow-discrete` on `display` is a requirement here to make this work.

Hereby reopening for further discussion.



-- 
GitHub Notification of comment by bramus
Please view or discuss this issue at https://github.com/w3c/csswg-drafts/issues/9500#issuecomment-4065949392 using your GitHub account


-- 
Sent via github-notify-ml as configured in https://github.com/w3c/github-notify-ml-config

Received on Monday, 16 March 2026 08:28:49 UTC