From 9e4aa9443b53ef38a3af1b269f4a949dd57e758f Mon Sep 17 00:00:00 2001 From: Dries Augustyns Date: Wed, 13 May 2026 19:22:17 +0200 Subject: [PATCH] fix: improve iframe height adjustment logic in EmailEditor component --- .../components/EmailEditor/EmailEditor.tsx | 34 ++++++++++++------- 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/apps/web/src/components/EmailEditor/EmailEditor.tsx b/apps/web/src/components/EmailEditor/EmailEditor.tsx index d7f80c9..4a1ad9d 100644 --- a/apps/web/src/components/EmailEditor/EmailEditor.tsx +++ b/apps/web/src/components/EmailEditor/EmailEditor.tsx @@ -306,21 +306,31 @@ export function EmailEditor({value, onChange, placeholder, subject, from, replyT iframeDoc.write(fullHtml); iframeDoc.close(); - // Auto-adjust iframe height to content + // Auto-adjust iframe height to content. Reset to a small value first so + // body content that uses % / vh heights doesn't lock the iframe to its + // previous size (which would otherwise cause the iframe to grow by the + // padding offset on every preview-device switch). const adjustHeight = () => { - if (iframe.contentWindow) { - const height = iframe.contentWindow.document.body.scrollHeight; - iframe.style.height = `${Math.max(400, height + 40)}px`; - } + if (!iframe.contentWindow) return; + iframe.style.height = '0px'; + const doc = iframe.contentWindow.document; + const height = Math.max( + doc.body?.scrollHeight ?? 0, + doc.documentElement?.scrollHeight ?? 0, + ); + iframe.style.height = `${Math.max(400, height + 40)}px`; }; - // Adjust height after content loads - if (iframe.contentWindow) { - iframe.contentWindow.addEventListener('load', adjustHeight); - // Also adjust immediately for already-loaded content - setTimeout(adjustHeight, 100); - setTimeout(adjustHeight, 300); // Fallback for slow-loading images - } + const timeouts = [ + window.setTimeout(adjustHeight, 100), + window.setTimeout(adjustHeight, 300), + ]; + iframe.contentWindow?.addEventListener('load', adjustHeight); + + return () => { + timeouts.forEach(window.clearTimeout); + iframe.contentWindow?.removeEventListener('load', adjustHeight); + }; } } // eslint-disable-next-line react-hooks/exhaustive-deps