Skip to content

Instantly share code, notes, and snippets.

@dorinvancea
Created December 16, 2024 10:32
Show Gist options
  • Save dorinvancea/f0eb05312eb8a3fb5081b854f5ead5b7 to your computer and use it in GitHub Desktop.
Save dorinvancea/f0eb05312eb8a3fb5081b854f5ead5b7 to your computer and use it in GitHub Desktop.
Astro custom Picture element
---
import Picture from "@components/Picture.astro";
---
<Picture
lightBasePath="/images/home/section-1"
darkBasePath="/images/home/dark/section-1"
alt="Screenshot"
width="1440px"
height="960px"
/>
---
interface Props {
lightBasePath: string;
darkBasePath: string;
alt: string;
width: string;
height: string;
}
const { lightBasePath, darkBasePath, alt, width, height } = Astro.props;
const breakpoints = [
{ media: "(max-width: 767px)", suffix: "@1x" },
{ media: "(min-width: 768px)", suffix: "@2x" },
{ media: "(min-width: 1200px)", suffix: "@3x" },
];
---
<picture class="image">
{/* Dark mode sources */}
{breakpoints.map(({ media, suffix }) => (
<source
srcset={`${darkBasePath}${suffix}.webp`}
media={`(prefers-color-scheme: dark) and ${media}`}
type="image/webp"
width={width}
height={height}
/>
))}
{/* Light mode sources */}
{breakpoints.map(({ media, suffix }) => (
<source
srcset={`${lightBasePath}${suffix}.webp`}
media={media}
type="image/webp"
width={width}
height={height}
/>
))}
{/* Fallback image */}
<img
src={`${lightBasePath}@1x.webp`}
alt={alt}
loading="lazy"
decoding="async"
width={width}
height={height}
/>
</picture>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment