From ff72dd27bce84f9321e2000d41033b8e5cccad9c Mon Sep 17 00:00:00 2001 From: Ray Thurn Void <53383860+raythurnvoid@users.noreply.github.com> Date: Thu, 29 May 2025 20:03:50 +0100 Subject: [PATCH] fix: transitions might render animated elements without animation styles applied for the duration of some rendering frames when they start (#16035) * fix: transitions might render animated elements without animation styles applied for the duration of some rendering frames when they starts * add changeset * Apply suggestions from code review --------- Co-authored-by: Rich Harris --- .changeset/tiny-poems-scream.md | 5 +++++ .../src/internal/client/dom/elements/transitions.js | 8 +++++++- 2 files changed, 12 insertions(+), 1 deletion(-) create mode 100644 .changeset/tiny-poems-scream.md diff --git a/.changeset/tiny-poems-scream.md b/.changeset/tiny-poems-scream.md new file mode 100644 index 0000000000..813972867a --- /dev/null +++ b/.changeset/tiny-poems-scream.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +fix: use `fill: 'forwards'` on transition animations to prevent flicker diff --git a/packages/svelte/src/internal/client/dom/elements/transitions.js b/packages/svelte/src/internal/client/dom/elements/transitions.js index cc895cbccb..38100e982c 100644 --- a/packages/svelte/src/internal/client/dom/elements/transitions.js +++ b/packages/svelte/src/internal/client/dom/elements/transitions.js @@ -381,9 +381,15 @@ function animate(element, options, counterpart, t2, on_finish) { // create a dummy animation that lasts as long as the delay (but with whatever devtools // multiplier is in effect). in the common case that it is `0`, we keep it anyway so that // the CSS keyframes aren't created until the DOM is updated - var animation = element.animate(keyframes, { duration: delay }); + // + // fill forwards to prevent the element from rendering without styles applied + // see https://github.com/sveltejs/svelte/issues/14732 + var animation = element.animate(keyframes, { duration: delay, fill: 'forwards' }); animation.onfinish = () => { + // remove dummy animation from the stack to prevent conflict with main animation + animation.cancel(); + // for bidirectional transitions, we start from the current position, // rather than doing a full intro/outro var t1 = counterpart?.t() ?? 1 - t2;