Search code examples
javascripthtmlformssveltesvelte-5

Svelte 5: Form briefly appears then disappears on page load when using conditional rendering for an image


I'm encountering a strange issue with a Svelte 5 component where a form briefly flashes on the screen for about half a second when the page loads, and then disappears. This happens when I have conditional rendering (using {#if}) for an image AND have bind:value={name} if I remove BOTH the form appears.

<script>
    let name = $state('');
    let name2 = 'test';
</script>

<body>
    <div class="container">
        {#if name.toLowerCase() === name2.toLowerCase()}
            <img src="example" alt="fantasma" class="fantasma" />
        {/if}
        <div class="box">
            <form class="form-group" action="">
                <label for="name" class="pergunta">Seu nome completo</label>
                <input type="text" id="name" class="input" bind:value={name} />
                <label for="date" class="pergunta">data de nascimento</label>
                <input type="date" id="data" class="input" />
            </form>
        </div>
    </div>
</body>

<style>
    .fantasma {
        width: 24%;
        height: auto;
    }
    .container {
        display: flex;
        justify-content: center;
        align-items: center;
        height: 100vh;
        flex-direction: column;
        background-color: #f0f0f0;
        margin: 0;
    }
    .form-group {
        display: flex;
        flex-direction: column;
        align-items: center;
    }
    .pergunta {
        margin-bottom: 7px;
    }
    .input {
        width: 300px;
        margin-bottom: 20px;
    }

    .box {
        width: 370px;
        height: 180px;
        margin: 40px;
        align-items: center;
        display: flex;
        flex-direction: column;
        justify-content: center;
        border-radius: 10px;
        background-color: red;
        border: 2.13px solid #ccc;
        box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
    }
</style>

I understand that initially, name is empty (''), so the condition name.toLowerCase() === name2.toLowerCase() evaluates to false. This prevents the image from rendering, which is the intended behavior. However, I don't understand why this causes the form to disappear after briefly appearing. It seems like the conditional rendering is somehow interfering with the initial rendering of the form itself.

What I've Tried:

  • Removing the {#if} block: Does not solve the problem.
  • Removing bind:value={name}: Does not solve the problem.
  • Removing both the {#if} and bind:value: Solves the form disappearing issue, but obviously removes the conditional image display.

Solution

  • You usually should not have a <body> in the component. When using SvelteKit, there already is one in the app.html, adding another likely causes a runtime error on hydration (check the browser console).

    What you see initially is the HTML from server-side rendering which gets fixed by the browser by removing the duplicate body tag. Once the JS loads and tries to hydrate the page, it walks the DOM expecting elements where there now are none.