Skip to content

Instantly share code, notes, and snippets.

@fsk1997
Last active January 26, 2025 07:50
Show Gist options
  • Save fsk1997/012f29061744e0b55a3168ec7c8d5248 to your computer and use it in GitHub Desktop.
Save fsk1997/012f29061744e0b55a3168ec7c8d5248 to your computer and use it in GitHub Desktop.
AstroJS x TailwindCSS Fading Image Component
---
import { Picture } from "astro:assets";
const {
src,
alt,
className,
draggable = false,
loading = "lazy",
quality = 50,
videoPoster
} = Astro.props;
function isVideo(str) {
return /\.(mp4|mov)$/.test(str);
}
const imgClassList = "w-full h-full object-cover object-center text-neutral-400/0"
---
{isVideo(src) ?
<div class:list={["relative w-full h-full", className]}>
<video
width="1440"
height="900"
class:list={[
"w-full h-full object-cover object-center",
"util-image",
className,
]}
autoplay
muted
loop
playsinline
poster={videoPoster}
>
<source src={src} type="video/mp4" />
Your browser does not support the video tag.
</video>
</div>
:
<Picture
pictureAttributes={{class: className + " block overflow-hidden"}}
width={src.width && src.width}
height={src.height && src.height}
inferSize={!src.width ? true : false}
class:list={[imgClassList]}
draggable={draggable}
src={src}
decoding={'async'}
loading={loading}
formats={['webp']}
alt={alt ? alt : ""}
quality={quality}
widths={[576, 1200, src.width]}
/>
}
<style>
.util-image{
@apply origin-center bg-neutral-100/[5%] scale-125 brightness-125 md:brightness-50 translate-y-4 blur-md;
}
.util-image.animate{
@apply scale-100 opacity-100 blur-none brightness-100 rotate-0 translate-y-0 transition-all duration-500 ease-in-out;
}
</style>
<script>
// https://medium.com/@salimian/the-intersection-observer-the-key-to-faster-element-tracking-by-scrolling-d5b2cce0a68f
// Define the Intersection Observer
const observer = new IntersectionObserver((entries, observer) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
// Get the animation classes from the `data-on-reach` attribute.
entry.target.classList.add("animate");
// Optionally, stop observing the element to improve performance.
observer.unobserve(entry.target);
}
});
}, {
rootMargin: '0px', // Trigger as soon as the element comes into view.
threshold: 0 // Even a pixel of visibility triggers the callback.
});
// Observe elements with the `data-on-reach` attribute.
document.querySelectorAll('.util-image').forEach(target => {
observer.observe(target);
});
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment