Svelte crossfade 为何使元素位移而非原地交叉淡入淡出?
问题描述
尝试基于布尔值实现两个元素的交叉淡入淡出效果,但实际运行时两个元素并未在同一位置切换,而是出现垂直位移,希望它们保持固定位置完成过渡。
代码示例
<script lang="ts"> import { crossfade } from "svelte/transition"; const [send, receive] = crossfade({ duration: 1500, }); let foo = true; function handleClick() { foo=!foo; } </script> <h1>My example</h1> <button on:click={handleClick}>Click me {foo}</button> <div> {#if foo} <div in:send={{ key: "a" }} out:receive={{ key: "a" }}> one </div> {:else} <div in:send={{ key: "a" }} out:receive={{ key: "a" }}> two </div> {/if} </div>
解决方案
出现垂直位移的核心原因是crossfade过渡会将元素设置为绝对定位,但包裹元素的父容器未设置相对定位,导致过渡元素相对于整个页面定位,而非父容器。只需给包裹两个元素的<div>添加相对定位样式,同时确保过渡期间父容器高度稳定即可解决:
修改后的代码如下:
<script lang="ts"> import { crossfade } from "svelte/transition"; const [send, receive] = crossfade({ duration: 1500, }); let foo = true; function handleClick() { foo=!foo; } </script> <h1>My example</h1> <button on:click={handleClick}>Click me {foo}</button> <!-- 添加相对定位和最小高度,确保容器尺寸稳定 --> <div style="position: relative; min-height: 1.5em;"> {#if foo} <div in:send={{ key: "a" }} out:receive={{ key: "a" }}> one </div> {:else} <div in:send={{ key: "a" }} out:receive={{ key: "a" }}> two </div> {/if} </div>
关键设置说明:
position: relative:让过渡元素的绝对定位相对于这个父容器,保证两个元素在同一位置切换。min-height: 1.5em:防止父容器在元素过渡时高度塌陷,避免页面布局抖动。
如果两个元素高度差异较大,还可以给每个过渡元素设置固定高度,或者让父容器取最大元素的高度,进一步确保过渡期间容器尺寸一致。
内容的提问来源于stack exchange,提问作者shainanigans
相关产品推荐
相关产品推荐

