sveltejs / sapper

The next small thing in web development, powered by Svelte
https://sapper.svelte.dev
MIT License
7k stars 434 forks source link

How to render transitions/animate routes on init without losing SSR? #1106

Open flayks opened 4 years ago

flayks commented 4 years ago

I'm facing this problem where on my homepage (although I would like to animate all routes on my site), I set a variable visible to false in order to run the transitions/in/out of my divs and components and make then nicely pop on the page (as this example for instance suggests it).

The thing is, if I do it this way, that kinda breaks the purpose of Sapper and SSR because on the server side, visible is always set to false, so it never renders the code when seeing the source code (so bad SEO, etc)

<script>
    let visible = false

    onMount(() => {
        visible = true
    })
</script>

{#if visible}

<div class="anim-mask" transition:fade={{ delay: 2000, duration: 800 }}>
    <div class="anim title-parallax" id="title-houses" data-aos={$loaded ? 'letters-translate-top' : null} data-aos-once="true">
        <h1 class="title-massive" aria-label="Houses">
            {@html fn.lettersToSpan('Houses')}
        </h1>
    </div>
</div>

{/if}

It works pretty well on the client side, but obviously on the server side, that's no code for the page, zip. So I was wondering, is there a way to do such a thing as running transitions on the page init with Sapper, most likely how we could do with Svelte with an intro: true on the App({ ... })? Or am I missing something or doing it wrong?

PS: Reproduction is a bit tricky as my site is quite complex and involves lots of components and elements, sorry about that


PS2 / WTF: I tried something, but this is nuts. If I do either of these options to try to simulate the server side by using process.browser, the content of my route is literally duplicated and I have 2 pages following each other. That is very odd and I have no clue where this could come from!

<script>
    let visible = process.browser ? false : true
</script>

<!-- OR -->

{#if visible || !process.browser}
...
Conduitry commented 4 years ago

What would displaying transitions on intro with SSR mean? That the server-rendered HTML contains the content, and then as soon as the JS loads and is run, the relevant content instantly disappears and then transitions in? SSR seems inherently incompatible with the idea of displaying transitions upon instantiating the component.

dimfeld commented 4 years ago

I suppose you could get rid of the #if and instead use style visibility:hidden or opacity:0 on your main div, and then in your onMount function change to visibility:visible or opacity:100 after the appropriate amount of time. You'd have to use CSS animations instead of Svelte transitions, though if you're just fading in that should be pretty simple.

Not sure what search engines do with content that's in the DOM but initially invisible though. I can imagine that they pay some attention to that nowadays to combat keyword stuffing but I'm just guessing.

flayks commented 4 years ago

What would displaying transitions on intro with SSR mean? That the server-rendered HTML contains the content, and then as soon as the JS loads and is run, the relevant content instantly disappears and then transitions in? SSR seems inherently incompatible with the idea of displaying transitions upon instantiating the component.

@Conduitry: Hm, okay. I guess transitions on first render with Sapper is not really a thing when using transition: or in: then?

I suppose you could get rid of the #if and instead use style visibility:hidden or opacity:0 on your main div, and then in your onMount function change to visibility:visible or opacity:100 after the appropriate amount of time. You'd have to use CSS animations instead of Svelte transitions, though if you're just fading in that should be pretty simple.

Not sure what search engines do with content that's in the DOM but initially invisible though. I can imagine that they pay some attention to that nowadays to combat keyword stuffing but I'm just guessing.

@dimfeld: That's an idea yea. Though, as I have more transitions all over I might consider switching to an animation library such as AnimeJS or something similar then.