Loading...
Loading...
Implement art direction for Next.js images using getImageProps(). Use when showing different images for different viewport sizes, such as homepage carousels with mobile vs desktop assets, different cropping/composition, or when mobile and desktop images differ completely.
npx skill4agent add flpbalada/my-opencode-config nextjs-image-art-direction| Approach | Purpose | Implementation |
|---|---|---|
| Art Direction | Different image content/composition | |
| Responsive Images | Same image, different sizes | |
getImageProps()getImageProps()useState()import { getImageProps } from 'next/image'
export default function ArtDirectedImage() {
// Common props shared across all image versions
const common = {
alt: 'Mountain landscape',
sizes: '100vw'
}
// Desktop version (landscape, higher quality)
const {
props: { srcSet: desktop },
} = getImageProps({
...common,
src: '/hero-desktop.jpg',
width: 1440,
height: 875,
quality: 80,
})
// Mobile version (portrait, smaller dimensions)
const {
props: { srcSet: mobile, ...rest },
} = getImageProps({
...common,
src: '/hero-mobile.jpg',
width: 750,
height: 1334,
quality: 70,
})
return (
<picture>
{/* Desktop: min-width 1000px */}
<source media="(min-width: 1000px)" srcSet={desktop} />
{/* Mobile: min-width 500px */}
<source media="(min-width: 500px)" srcSet={mobile} />
{/* Fallback img element (rendered if no media query matches) */}
<img {...rest} style={{ width: '100%', height: 'auto' }} />
</picture>
)
}srcwidthheightqualityaltsizes<picture><source>media<img><source><picture>
<source media="(min-width: 1000px)" srcSet={desktop} />
<source media="(min-width: 500px)" srcSet={tablet} />
<img {...rest} style={{ width: '100%', height: 'auto' }} />
</picture><picture>
<source media="(max-width: 499px)" srcSet={mobile} />
<source media="(max-width: 999px)" srcSet={tablet} />
<img {...rest} style={{ width: '100%', height: 'auto' }} />
</picture>preloadloading="eager"// BAD: Would load both desktop and mobile
getImageProps({
src: '/desktop.jpg',
preload: true, // Don't do this!
})
// BAD: Same problem
getImageProps({
src: '/desktop.jpg',
loading: 'eager', // Don't do this!
})fetchPriority="high"const common = {
alt: 'Hero image',
fetchPriority: 'high', // Only load the matching image eagerly
}alt// BAD: Only describes desktop version
const common = { alt: 'Wide panoramic mountain landscape' }
// GOOD: Describes both versions
const common = { alt: 'Mountain landscape with snow-capped peaks' }placeholdergetImageProps()placeholderimport { getImageProps } from 'next/image'
export default function Hero() {
const common = {
alt: 'Team collaboration in modern office',
sizes: '100vw',
fetchPriority: 'high',
}
// Large desktop: Full office scene
const { props: { srcSet: desktop } } = getImageProps({
...common,
src: '/hero-office-wide.jpg',
width: 1920,
height: 1080,
quality: 85,
})
// Tablet: Focused team shot
const { props: { srcSet: tablet } } = getImageProps({
...common,
src: '/hero-team-focused.jpg',
width: 1024,
height: 768,
quality: 80,
})
// Mobile: Single person portrait
const { props: { srcSet: mobile, ...rest } } = getImageProps({
...common,
src: '/hero-person-portrait.jpg',
width: 750,
height: 1334,
quality: 75,
})
return (
<section className="relative">
<picture>
<source media="(min-width: 1200px)" srcSet={desktop} />
<source media="(min-width: 768px)" srcSet={tablet} />
<source media="(min-width: 500px)" srcSet={mobile} />
<img
{...rest}
className="w-full h-auto object-cover"
style={{ maxHeight: '80vh' }}
/>
</picture>
<div className="absolute inset-0 flex items-center justify-center">
<h1 className="text-white text-4xl font-bold drop-shadow-lg">
Welcome to Our Platform
</h1>
</div>
</section>
)
}getImageProps()image-set()import { getImageProps } from 'next/image'
function getBackgroundImage(srcSet = '') {
const imageSet = srcSet
.split(', ')
.map((str) => {
const [url, dpi] = str.split(' ')
return `url("${url}") ${dpi}`
})
.join(', ')
return `image-set(${imageSet})`
}
export default function HeroBackground() {
const {
props: { srcSet },
} = getImageProps({
alt: '',
width: 1920,
height: 1080,
src: '/hero-bg.jpg',
quality: 80,
})
const backgroundImage = getBackgroundImage(srcSet)
return (
<main
style={{
height: '100vh',
width: '100vw',
backgroundImage,
backgroundSize: 'cover',
backgroundPosition: 'center',
}}
>
<h1>Content Here</h1>
</main>
)
}getImageProps()altsizes<source>fetchPriority="high"preloadpreloadloading="eager"placeholdergetImageProps()<img>