Apply different transition on smaller screens

84 views Asked by At

I would like to apply a different transition when the device width is below a certain threshold. Similar to this question, but instead of just passing different transition parameters per breakpoint, I want to apply a different transition.

For example applying a fly transition by default, but then on screens smaller than 600px in width, apply a simple fade transition.

3

There are 3 answers

2
brunnerh On BEST ANSWER

Transitions are just functions, so you can just move the size check into a custom transition function and call fly/fade, something like:

function fadeOrFly(node) {
    return isScreenSmall() ? fade(node) : fly(node, { y: -100 });
}
<div transition:fadeOrFly>

REPL

0
Sámal Rasmussen On

Same solution as @brunnerh, but using in and out, as it makes the transition a little bit more robust to viewport change while the element is in view.

function fadeOrFly(node) {
    return isScreenSmall() ? fade(node) : fly(node, { y: -100 });
}
<div in:fadeOrFly out:fadeOrFly>

REPL: https://svelte.dev/repl/256d99b74bbe462db006e7e1b84e268f?version=4.2.9

0
Brian On

Another way to do this is with CSS variables (custom properties).

This lets you specify what transition you want from your CSS using regular media queries (vs switching based on isScreenSmall() or similar functions).

Set some custom property that designates the transition you want to use (using any identifier you like), then switch the transition based on that.

Example of a drawer that slides in from the right on large screens, and the bottom on small screens:

<script>
    import { fly } from 'svelte/transition';

    function responsiveTransition(node) {
        const dir = getCssVar('--dir', node); // some utility function
        switch (dir) {
            case 'bottom':
                return fly(node, { y: '100%', duration: 300 });
            case 'right':
                return fly(node, { x: '100%', duration: 250 });
        }
    }
</script>

<div class="drawer" in:responsiveTransition out:responsiveTransition>...</div>

<style>
    .drawer {
        --dir: bottom;
    }
    @media (min-width: 600px) {
        .drawer {
            --dir: right;
        }
    }
</style>