Open weepy opened 5 years ago
What would these measure? Which DOM properties are you referring to?
dom.scrollLeft
and dom.scrollTop
So e.g if I want to programmatically set scrollLeft of a dom element from a reactive property or tweenable store prop.
I like this, I've wanted it a couple of times myself. Opened #3895. It uses scrollLeft
and scrollTop
as the binding names, rather than making it consistent with <svelte:window>
but inconsistent with the DOM
+1 for wanting bind:scrollLeft
/bind:scrollTop
.
@Rich-Harris I saw that you identified some issues with your initial implementation approach. I could take a crack at fixing it, if you can point me in the right direction.
We've been wanting this feature as well, to implement a scroll carousel functionality using CSS scroll snapping on a PWA. But the app needs to know the current scroll position!
What would you folks recommend as an interim solution? Would it be something like element.addEventListener("scroll", ...)
?
Would love an interim solution if anyone worked one out!
This would've been nice.
I thought it's already implemented since we have it for <svelte:window>
.
Requires a few lines, but falling back to EventListeners this is the best I could come up with, using bind
:
<script>
import { onMount } from 'svelte';
let elem;
let elemScrollTop = 0; // This will be reactive
onMount(() => {
// Update elemScrollTop every time the user scrolls
elem.addEventListener('scroll', ({ target }) => (elemScrollTop = target.scrollTop));
});
</script>
<div bind:this={elem}></div>
I couldn't figure out a solution leveraging svelte's reactivity to update scrollTop
/scrollLeft
. If someone finds a better solution I'd love to know too.
This would be a massive feature for my project. We have an in-house carousel that we've built, and it's extremely complex because we had to implement part of this ourselves.
I couldn't figure out a solution leveraging svelte's reactivity to update
scrollTop
/scrollLeft
. If someone finds a better solution I'd love to know too.
What about
<script>
let elem;
let elemScrollTop = 0;
</script>
<div bind:this={elem} on:scroll={() => (elemScrollTop = elem.scrollTop)}></div>
or
<script>
let elemScrollTop = 0;
</script>
<div on:scroll={(ev) => (elemScrollTop = ev.target.scrollTop)}></div>
?
In case you're trying to find out whether an element entered or left the viewport, I found the nice svelte-inview action. However support of scrollX
/ scrollY
for any element would be greatly appreciated.
Here's my little action :
const scrollLeft = writable(0)
export function scrollX(node, store) {
store.subscribe(val => node.scrollLeft = val)
node.addEventListener('scroll', (e) => {
store.set(e.target.scrollLeft)
})
}
use like:
<div use:scrollX={scrollLeft}> ...
guys, any updates on this?
This would be very useful for triggering an animation when a child element becomes visible!
A workaround I came up with for Svelte 5 runes
let scrollY = $state(0)
...
const bindScrollY = (node: HTMLElement, val: { scrollY: number }) => {
$effect(() => {
node.scrollTop = scrollY
})
const handle = (e: any) => {
scrollY = e.target.scrollTop
}
node.addEventListener('scroll', handle)
return {
destroy: () => removeEventListener('scroll', handle)
}
}
...
<div ... use:bindScrollY={{ scrollY }}>
Is there a reason why there's no
bind:scrollX
for dom nodes ? I see there are for window. I rolled my own solution, but it felt like it should be supported!