Description
Describe the bug
Bear with me, this is a bit of an edge case.
If you have code like this...
<script>
let h = 0;
const html = '<div style="height: 50vh"></div><div style="height: 100vh; background: salmon"><h3 id="foo">this should be at the top of the page</h3></div>';
</script>
<div bind:clientHeight={h} /><main>{@html html}</main>
it will compile with hydratable: true
to this:
/* omitted */
l(nodes) {
div = claim_element(nodes, "DIV", {});
children(div).forEach(detach);
main = claim_element(nodes, "MAIN", {});
var main_nodes = children(main);
main_nodes.forEach(detach);
this.h();
},
h() {
add_render_callback(() => /*div_elementresize_handler*/ ctx[1].call(div));
},
m(target, anchor) {
insert_hydration(target, div, anchor);
div_resize_listener = add_resize_listener(div, /*div_elementresize_handler*/ ctx[1].bind(div));
insert_hydration(target, main, anchor);
main.innerHTML = html;
},
/* omitted */
Between main_nodes.forEach(detach)
and main.innerHTML = html
, the addition of the resize listener causes a reflow that, long story short, results in you losing your scroll position if you were previously scrolled to #foo
and there's not much content on the page other than the contents of {@html ...}
. This is currently visible on the SvelteKit docs: sveltejs/kit#4216. (Only on Chrome, not Firefox.)
Removing the bind:clientHeight
(or placing it below the {@html ...}
) prevents the bug, as would using a ResizeObserver
instead of the resize listener hack. But the biggest mystery is why we're waiting until the mount phase (m
) to do innerHTML = html
instead of the claim phase (l
).
(Aside: it would be nice if there was a way to say 'you don't need to replace me, I promise my contents won't have changed since SSR' — {@html:leavemealone post.html}
or whatever.)
Reproduction
Open this StackBlitz repro and go to the standalone version: https://sveltejs-kit-template-default-pm2sdq--3000.local.webcontainer.io/
Logs
No response
System Info
System:
OS: macOS 12.0.1
CPU: (10) arm64 Apple M1 Max
Memory: 90.30 MB / 32.00 GB
Shell: 5.8 - /bin/zsh
Binaries:
Node: 16.13.1 - ~/.nvm/versions/node/v16.13.1/bin/node
Yarn: 1.22.17 - ~/.nvm/versions/node/v16.13.1/bin/yarn
npm: 8.1.2 - ~/.nvm/versions/node/v16.13.1/bin/npm
Browsers:
Chrome: 98.0.4758.109
Firefox: 97.0.1
Safari: 15.1
npmPackages:
svelte: ^3.43.0 => 3.44.2
Severity
annoyance