skip to Main Content

I have a page that has several stages, and I want to add transitions between them.

{#if state === 1}
 <div class="red" transition:fade/>
{:else if state === 2}
 <div class="blue" transition:fade/>
{:else if state === 3}
 <div class="green" transition:fade/>
{/if}

However, when switching from one state to the next, the next one appears at the same time as the previous one is still disappearing, so the two states would appear at the same time for the duration of the transition.

What is the best approach (the approach that requires adding the least amount of code) to make one state’s fade in connect with another state’s fade out?

Here is a code sandbox link: https://codesandbox.io/p/sandbox/priceless-pine-kgrh7w

2

Answers


  1. One way would be to position the elements on top of each other with the help of a wrapper element

    REPL

    <script>
        import { fade } from 'svelte/transition';
        let state = 1;
    
        function handleClick() {
            state += 1;
            if (state == 4) state = 1;
        }
    </script>
    
    <main>
        <button on:click={handleClick}> Change </button>
        <div class="wrapper">
            {#if state === 1}
                <div class="red" transition:fade/>
            {:else if state === 2}
                <div class="blue" transition:fade/>
            {:else if state === 3}
                <div class="green" transition:fade/>
            {/if}
        </div>
    </main>
    
    <style>
        button {
            background: #ff3e00;
            color: white;
            border: none;
            padding: 8px 12px;
            border-radius: 2px;
        }
    
        .wrapper {
            display: grid;      
        }
    
        .wrapper > div {
            grid-column: 1;
            grid-row: 1;
            width: 100px;
            height: 100px;
        }
    
        .red {
            background: red;
        }
    
        .blue {
            background: blue;
        }
    
        .green {
            background: green;
        }
    </style>
    
    Login or Signup to reply.
  2. I often use a wrapper to stack items in place:

    .stack { display: grid; }
    .stack > * { grid-area: 1 / 1; } /* potentially add place-self to center */
    

    REPL

    This will cause an overlapping fade.

    If that is not what you want, you can instead add a delay to to each transition that waits for the previous one to finish.

    const inOptions = { duration: 400, delay: 400 };
    const outOptions = { duration: 400 };
    
    {#if state === 1}
     <div class="red" in:fade={inOptions} out:fade={outOptions}/>
    {:else if state === 2}
     <div class="blue" in:fade={inOptions} out:fade={outOptions}/>
    {:else if state === 3}
     <div class="green" in:fade={inOptions} out:fade={outOptions}/>
    {/if}
    

    REPL

    (The stack could still be added for safety if animations end up not fully in sync. Or increase the delay to a bit more than the duration.)

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search