N
Nuxt2mo ago
tierra

NuxtImage Fade In

Hello! Can someone explain to me how I can add a basic fade effect after the image has been loaded? I tried this
<script setup lang="ts">
// …
const isLoaded = ref(false)

function onLoad() {
isLoaded.value = true
}
</script>

<template>
<NuxtImg
:src="props.src"
loading="lazy"
:width="props.width"
:height="props.height"
:sizes="props.sizes"
quality="80"
:data-loaded="isLoaded"
:alt="props.alt"
class="opacity-0 transition-opacity duration-400 data-[loaded=true]:(opacity-100)"
@load="onLoad"
/>
</template>
<script setup lang="ts">
// …
const isLoaded = ref(false)

function onLoad() {
isLoaded.value = true
}
</script>

<template>
<NuxtImg
:src="props.src"
loading="lazy"
:width="props.width"
:height="props.height"
:sizes="props.sizes"
quality="80"
:data-loaded="isLoaded"
:alt="props.alt"
class="opacity-0 transition-opacity duration-400 data-[loaded=true]:(opacity-100)"
@load="onLoad"
/>
</template>
However, this works on first sight. But when I am switching pages back and forth. Images won't load again. It looks like as if cached images are not firing the load event anymore?
2 Replies
kapa.ai
kapa.ai2mo ago
Hi @tierra. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave: ---------------------- To add a basic fade effect after the image has been loaded using NuxtImg, you're on the right track. However, you've encountered an issue with cached images not triggering the load event when navigating between pages. Let's address this and provide a solution. First, your approach of using the @load event and a reactive variable to control the opacity is correct. However, as you've noticed, cached images might not trigger the load event on subsequent page visits. To solve this, we can leverage the placeholder prop of NuxtImg, which will ensure the fade effect works consistently, even with cached images. Here's how you can modify your code:
<script setup lang="ts">
import { ref } from 'vue'

const isLoaded = ref(false)

function onLoad() {
isLoaded.value = true
}
</script>

<template>
<NuxtImg
:src="props.src"
loading="lazy"
:width="props.width"
:height="props.height"
:sizes="props.sizes"
quality="80"
placeholder
:alt="props.alt"
class="transition-opacity duration-400"
:class="{ 'opacity-0': !isLoaded, 'opacity-100': isLoaded }"
@load="onLoad"
/>
</template>
<script setup lang="ts">
import { ref } from 'vue'

const isLoaded = ref(false)

function onLoad() {
isLoaded.value = true
}
</script>

<template>
<NuxtImg
:src="props.src"
loading="lazy"
:width="props.width"
:height="props.height"
:sizes="props.sizes"
quality="80"
placeholder
:alt="props.alt"
class="transition-opacity duration-400"
:class="{ 'opacity-0': !isLoaded, 'opacity-100': isLoaded }"
@load="onLoad"
/>
</template>
Key changes and explanations: 1. We've added the placeholder prop to NuxtImg. This ensures that a placeholder is displayed while the image is loading, even for cached images NuxtImg placeholder (https://image.nuxt.com/usage/nuxt-img#placeholder). 2. We've modified the class binding to use Vue's dynamic class syntax, which is more reliable than data attributes for this use case. 3. The loading="lazy" attribute is kept, which is good for performance NuxtImg loading (https://image.nuxt.com/usage/nuxt-img#loading). 4. We're still using the @load event to trigger the fade-in effect NuxtImg events (https://image.nuxt.com/usage/nuxt-img#events). This approach should work consistently, even when navigating between pages, because the placeholder ensures that the image loading process is triggered each time, regardless of whether the image is cached or not. If you still encounter issues with this approach, you might want to consider using the useImage() composable to generate a placeholder, which gives you more control over the process:
<script setup>
import { ref } from 'vue'

const img = useImage()
const isLoaded = ref(false)

function onLoad() {
isLoaded.value = true
}
</script>

<template>
<NuxtImg
:src="props.src"
:placeholder="img(props.src, { h: 10, f: 'png', blur: 2, q: 50 })"
loading="lazy"
:width="props.width"
:height="props.height"
:sizes="props.sizes"
quality="80"
:alt="props.alt"
class="transition-opacity duration-400"
:class="{ 'opacity-0': !isLoaded, 'opacity-100': isLoaded }"
@load="onLoad"
/>
</template>
<script setup>
import { ref } from 'vue'

const img = useImage()
const isLoaded = ref(false)

function onLoad() {
isLoaded.value = true
}
</script>

<template>
<NuxtImg
:src="props.src"
:placeholder="img(props.src, { h: 10, f: 'png', blur: 2, q: 50 })"
loading="lazy"
:width="props.width"
:height="props.height"
:sizes="props.sizes"
quality="80"
:alt="props.alt"
class="transition-opacity duration-400"
:class="{ 'opacity-0': !isLoaded, 'opacity-100': isLoaded }"
@load="onLoad"
/>
</template>
This method gives you more control over the placeholder generation and should ensure the fade effect works consistently across page navigations NuxtImg placeholder with useImage (https://image.nuxt.com/usage/nuxt-img#placeholder). ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai2mo ago
<@910553251949195276> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
Want results from more Discord servers?
Add your server