Svelte使用#if块控制flex容器元素显隐时固定元素如何平滑调整尺寸
问题原因
你遇到的跳变问题核心是:flex布局下flex:1元素的高度由容器剩余空间自动计算,CSS默认不支持auto高度的平滑过渡,所以会直接跳变到新尺寸。以下两种方案都不需要修改{#if}逻辑,也不用引入{#each}块:
方案1:兼容所有现代浏览器(JS配合补间动画)
修改后的JS代码
import { fly } from 'svelte/transition' import { tweened } from 'svelte/motion' import { cubicOut } from 'svelte/easing' // 统一动画时长,保证两个元素动画完全同步 const TRANSITION_DURATION = 2000 let add = false // 绑定永久元素的DOM引用 let permanentEl // 用tweened存储高度值,实现平滑数值过渡 const permanentHeight = tweened('auto', { duration: TRANSITION_DURATION, easing: cubicOut }) // 监听显隐状态变化,更新永久元素高度 $: if (permanentEl) { // 先临时设为auto拿到目标高度 permanentEl.style.height = 'auto' const targetHeight = permanentEl.offsetHeight // 触发平滑过渡到目标高度 permanentHeight.set(targetHeight) }
修改后的HTML代码
<main> {#if add} <div transition:fly={{ y: -200, duration: TRANSITION_DURATION }} class='box' id='add'> 新增元素 </div> {/if} <div class='box' id='permanent' bind:this={permanentEl} style="height: {$permanentHeight}px" > 我希望父容器新增元素时,这个元素可以平滑调整尺寸,请问能否不使用each块实现该需求? </div> <button on:click={() => add = !add}> {add ? '移除' : '添加'}元素 </button>
修改后的CSS代码
main { height: 100%; display: flex; flex-direction: column; gap: 10px; } .box { border: 1px solid black; min-height: 50px; } #permanent { flex: 1; display: flex; text-align: center; flex-direction: column; justify-content: center; overflow: hidden; /* 防止过渡期间内容溢出 */ }
方案2:纯CSS实现(写法更简单,需要浏览器支持:has选择器)
不需要修改JS和HTML的逻辑,仅修改CSS即可:
main { height: 100%; display: grid; grid-template-rows: var(--add-row, 0fr) 1fr auto; gap: 0 10px; transition: grid-template-rows 2000ms ease, gap 2000ms ease; } /* 新增元素存在时修改网格轨道高度 */ main:has(#add) { --add-row: auto; gap: 10px; } #add { overflow: hidden; } .box { border: 1px solid black; min-height: 50px; } #permanent { display: flex; text-align: center; flex-direction: column; justify-content: center; }
内容的提问来源于stack exchange,提问作者seanlucano
相关产品推荐
相关产品推荐

