diff --git a/src/lib/components/MarkdownRenderer.svelte b/src/lib/components/MarkdownRenderer.svelte index 8c4f14c..24d56c6 100644 --- a/src/lib/components/MarkdownRenderer.svelte +++ b/src/lib/components/MarkdownRenderer.svelte @@ -400,14 +400,35 @@ codeBlock.classList.remove('is-open'); codeBlock.classList.add('is-closed'); } else { + // 暂时关闭 transition 以获取真实的 scrollHeight (包括 padding) + const originalTransition = codeEl.style.transition; + codeEl.style.transition = 'none'; codeBlock.classList.remove('is-closed'); codeBlock.classList.add('is-open'); - codeEl.style.maxHeight = codeEl.scrollHeight + 'px'; + codeEl.style.maxHeight = 'none'; + + const targetHeight = codeEl.scrollHeight; + + // 恢复关闭状态,准备开始动画 + codeBlock.classList.remove('is-open'); + codeBlock.classList.add('is-closed'); + codeEl.style.maxHeight = '0px'; + void codeEl.offsetHeight; // 强制 reflow + + // 恢复 transition 并开始动画 + codeEl.style.transition = originalTransition; + codeBlock.classList.remove('is-closed'); + codeBlock.classList.add('is-open'); + codeEl.style.maxHeight = targetHeight + 'px'; + const handler = (e: Event) => { - if (e.target === codeEl && codeBlock.classList.contains('is-open')) { - codeEl.style.maxHeight = 'none'; + const transEvent = e as TransitionEvent; + if (e.target === codeEl && transEvent.propertyName === 'max-height') { + if (codeBlock.classList.contains('is-open')) { + codeEl.style.maxHeight = 'none'; + } + codeEl.removeEventListener('transitionend', handler); } - codeEl.removeEventListener('transitionend', handler); }; codeEl.addEventListener('transitionend', handler); }