Back to skills

skills/nextjs-image-art-direction/SKILL.md

nextjs-image-art-direction

Use art direction when viewport size needs different image content or crop.

npx skills add https://github.com/flpbalada/fb-skills --skill nextjs-image-art-direction
GitHub

Skill Docs

Use art direction when viewport size needs different image content or crop.

When to Use

  • Mobile and desktop use different assets
  • Crop, focal point, or content hierarchy changes by viewport
  • Carousel has separate mobile and desktop images

Goal

Render one correct image per viewport. Keep Next.js image optimization. Avoid loading unused images.

Rules

  • Use <picture> with <source> and final <img>.
  • Use getImageProps() for each asset.
  • Share alt and sizes.
  • Make alt accurate for all variants.
  • Order sources so first matching media query wins.
  • Do not use preload or loading="eager".
  • Use fetchPriority="high" for LCP image when needed.
  • Do not use placeholder with getImageProps().

Pattern

import { getImageProps } from 'next/image'

export function HeroImage() {
  const common = { alt: 'Mountain landscape', sizes: '100vw' }
  const { props: { srcSet: desktop } } = getImageProps({
    ...common,
    src: '/hero-desktop.jpg',
    width: 1440,
    height: 875,
  })
  const { props: { srcSet: mobile, ...rest } } = getImageProps({
    ...common,
    src: '/hero-mobile.jpg',
    width: 750,
    height: 1334,
  })

  return (
    <picture>
      <source media="(min-width: 768px)" srcSet={desktop} />
      <img {...rest} style={{ width: '100%', height: 'auto' }} />
    </picture>
  )
}

Flow

  1. Confirm content changes, not only size.
  2. Pick assets per breakpoint.
  3. Define common props.
  4. Generate srcSet per asset.
  5. Put <source> before fallback <img>.
  6. Test desktop, tablet, and mobile.
  7. Confirm only matching image loads.

Output

## Art Direction Plan

Use case: [why different images are needed]
Breakpoints:
- [media query]: [asset], [width]x[height]
- fallback: [asset], [width]x[height]

Common props:
- alt: [text]
- sizes: [value]
- priority: [fetchPriority if LCP]