Search code examples
javascriptvue.jsvuejs3nuxt.jsnuxt3.js

VueUse useIntersectionObserver causes initial flash before transition


I'm using useIntersectionObserver from VueUse to apply a fade-in transition on elements when they come into view. However, on initial page load, the elements briefly appear before the intersection observer triggers, causing a flash and applying the fade-in effect with a delay.

I want the elements to fade in smoothly as soon as the page loads, without this initial flash. Here’s the reproduction: https://stackblitz.com/edit/nuxt-starter-vd6hka?file=app%2Fpages%2Findex.vue

Observer component:

<template>
  <div>
    <div ref="observerRef">
      <div :class="{ 'fade-in': isVisible }">
        <img crossOrigin="anonymous" src="https://unsplash.it/600/400" />
      </div>
    </div>
  </div>
</template>

<script setup>
import { useIntersectionObserver } from '@vueuse/core';

const observerRef = ref(null);
const isVisible = ref(false);

const { stop } = useIntersectionObserver(
  observerRef,
  ([{ isIntersecting }]) => {
    isVisible.value = isIntersecting;
    if (isIntersecting) stop();
  }
);
</script>

Looking for a possible solution.


Solution

  • DOM APIs like IntersectionObserver are not guaranteed to be synchronous. It takes some time between an element being visible on the screen and an observer being triggered.

    div that needs a transition should have visible: hidden style when it have fade-in, either through CSS class or dynamic styles:

    <div
      :class="{ 'fade-in': isVisible }"
      :style="{ visibility: isVisible ? 'visible' : 'hidden' }"
    >