sveltesveltekitsvelte-transition

Sveltekit: different in|out FLY transition (vertical and horizontal) based on screen width


I'm learning Sveltekit and i am trying to figure out how i can implent two differently oriented in:fly/out:fly based on the width of the screen (mobile and monitor for example).

Something like: IF on monitor screen (min-width: 640px) then in:fly from the left ELSE (if on mobile phone) in:fly from the top

This is an example of my code at the moment:

<script lang="ts">
    import { fade, fly } from 'svelte/transition';

    /* Navigation menu */
    const navigation = [
        {
            title: 'Home',
            href: '/'
        },
        {
            title: 'About',
            href: '/about'
        },
        {
            title: 'Projects',
            href: '/projects'
        },
        {
            title: 'Contact',
            href: '/contact'
        }
    ];
</script>
<nav class="navigation" in:fade={{ duration: 100 }} out:fade={{ duration: 100 }}>
    <ul
        class="navigation__content"
        in:fly={{ x: -1000, duration: 300 }}
        out:fly={{ x: -1000, duration: 300 }}
    >
        {#each navigation as navItem}
            <li class="navigation__page">
                <a href={navItem.href}>{navItem.title}</a>
            </li>
        {/each}
    </ul>
</nav>

I am not quite sure how i could implement something like this, i was thinking about a #if statement. I searched the web but couldn't find anything useful.


Solution

  • You can create a store that programmatically matches a media query and switch out the transition arguments accordingly, e.g.

    import { onMount } from 'svelte';
    import { writable } from 'svelte/store';
    
    export function mediaQueryStore(query) {
        const store = writable(false);
        
        onMount(() => {
            const mediaQueryList = window.matchMedia(query);
    
            const onChange = () => store.set(mediaQueryList.matches);
            mediaQueryList.addEventListener('change', onChange);
            onChange();
    
            return () => mediaQueryList.removeEventListener('change', onChange);
        });
    
        return { subscribe: store.subscribe };
    }
    
    const small = mediaQueryStore('(max-width: 600px)');
    
    <div transition:fly={$small ?
      { x: -1000, duration: 300 } : 
      { y: -1000, duration: 300 }}>
    

    (If in/out animations are the same, you can just use transition:...)

    REPL