svelte
svelte copied to clipboard
Component styles flicker/blink with SSR mode on
Describe the bug
When applying stylings to components or pages, on SSR mode, first server stylings get rendered, and then client ones.
In some cases, when components / pages use more 'dynamic' data like slots, $$restProps with class names, lists, etc., what oddly happens is that there is a 'flicker', where server stylings do not seem to match client ones.
Below is a video with two examples of when this happens:
https://github.com/sveltejs/kit/assets/61620873/e5688342-1c23-4994-a4ba-807fc1247e1b
Reproduction
About twenty lines: https://www.sveltelab.dev/vg1t4x2cb8n84f4
Logs
No response
System Info
I've spoken to a number of people so I don't think that it is a device-specific thing. But anyway:
System:
OS: macOS 13.3.1
CPU: (8) arm64 Apple M1
Memory: 83.23 MB / 16.00 GB
Shell: 5.9 - /bin/zsh
Binaries:
Node: 19.6.0 - /opt/homebrew/bin/node
Yarn: 1.22.11 - /opt/homebrew/bin/yarn
npm: 9.4.0 - /opt/homebrew/bin/npm
Browsers:
Brave Browser: 113.1.51.114
Safari: 16.4
npmPackages:
@sveltejs/adapter-auto: ^1.0.0-next.91 => 1.0.0-next.91
@sveltejs/kit: next => 1.0.0-next.589
svelte: ^3.55.1 => 3.55.1
vite: ^4.0.0 => 4.1.1
Severity
annoyance
Additional Information
No response
The same issue happens even when setting export const csr = false
. Interestingly, the only workaround seems to be wrapping for loops in a flexbox.
<div style="display:flex;">
{#each item as item}
<!-- represent the item details in a tailwind card -->
<div class="w-64 inline-block bg-pink">
<div>
<a href="/media/{item}">Page</a>
</div>
</div>
{/each}
</div>
But I would suggest this approach be avoided. When setting e.g. 5 divs (without the for loop), there are no spaces. Only through the above do they have spaces on the server-rendered HTML, and then revert to no spaces / gaps as expected (see repro). So this seems to be more of a workaround than expected behavior.
This issue is not caused by when styles are applied, but differences in the whitespace present in the SSR markup and the client-side rendered elements.
The SSR markup inserts a text node with "\n " between each child div:
But when client-side rendered, those nodes are removed:
There are multiple whitespace issues open in the Svelte repo, so not sure if this is a duplicate or not (or what workarounds would be). Transferring over there for now.
I've looked through the issues and I don't see an exact duplicate.
If it wasn't clear from the OP, if you don't need SSR, disabling it avoids the issue:
// +layout.ts
export const ssr = false;