@@ -369,6 +369,8 @@ function create_transition(dom, init, direction, effect) {
369
369
} ,
370
370
// out
371
371
o ( ) {
372
+ // @ts -ignore
373
+ const has_keyed_transition = dom . __animate === true ;
372
374
const needs_reverse = direction === 'both' && curr_direction !== 'out' ;
373
375
curr_direction = 'out' ;
374
376
if ( animation === null || cancelled ) {
@@ -385,6 +387,29 @@ function create_transition(dom, init, direction, effect) {
385
387
/** @type {Animation | TickAnimation } */ ( animation ) . play ( ) ;
386
388
}
387
389
}
390
+ // If we're outroing an element that has an animation, then we need to fix
391
+ // its position to ensure it behaves nicely without causing layout shift.
392
+ if ( has_keyed_transition ) {
393
+ const style = getComputedStyle ( dom ) ;
394
+ const position = style . position ;
395
+
396
+ if ( position !== 'absolute' && position !== 'fixed' ) {
397
+ const { width, height } = style ;
398
+ const a = dom . getBoundingClientRect ( ) ;
399
+ dom . style . position = 'absolute' ;
400
+
401
+ dom . style . width = width ;
402
+ dom . style . height = height ;
403
+ const b = dom . getBoundingClientRect ( ) ;
404
+ if ( a . left !== b . left || a . top !== b . top ) {
405
+ const style = getComputedStyle ( dom ) ;
406
+ const transform = style . transform === 'none' ? '' : style . transform ;
407
+ dom . style . transform = `${ transform } translate(${ a . left - b . left } px, ${
408
+ a . top - b . top
409
+ } px)`;
410
+ }
411
+ }
412
+ }
388
413
} ,
389
414
// cancel
390
415
c ( ) {
@@ -432,10 +457,16 @@ function is_transition_block(block) {
432
457
export function bind_transition ( dom , get_transition_fn , props_fn , direction , global ) {
433
458
const transition_effect = /** @type {import('./types.js').EffectSignal } */ ( current_effect ) ;
434
459
const block = current_block ;
460
+ const is_keyed_transition = direction === 'key' ;
435
461
436
462
let can_show_intro_on_mount = true ;
437
463
let can_apply_lazy_transitions = false ;
438
464
465
+ if ( is_keyed_transition ) {
466
+ // @ts -ignore
467
+ dom . __animate = true ;
468
+ }
469
+
439
470
/** @type {import('./types.js').Block | null } */
440
471
let transition_block = block ;
441
472
while ( transition_block !== null ) {
@@ -479,7 +510,7 @@ export function bind_transition(dom, get_transition_fn, props_fn, direction, glo
479
510
const init = ( from ) =>
480
511
untrack ( ( ) => {
481
512
const props = props_fn === null ? { } : props_fn ( ) ;
482
- return direction === 'key'
513
+ return is_keyed_transition
483
514
? /** @type {import('./types.js').AnimateFn<any> } */ ( transition_fn ) (
484
515
dom ,
485
516
{ from : /** @type {DOMRect } */ ( from ) , to : dom . getBoundingClientRect ( ) } ,
0 commit comments