SuperAPI AI Directory

imagery

Design & creation

View repository

Updated 10-15 19:52

About this skill

Pictures in the Interface

The default is no photograph. Product UI earns its texture from type, spacing, and material, and every picture you add is an aspect ratio to lock, a placeholder to design, two themes to survive, and bytes on the critical path. A picture belongs only when the picture is the content: something a user uploaded, a product being sold, a chart of their data, or a screenshot of the thing you actually built. Benji Taylor's site is the reference case — 53 device frames showing real product work, and zero stock photographs, no 3D render, no hero image, not even a photo of himself. When a picture does belong, it ships with its ratio locked before a single byte arrives.

The sibling to keep straight is iconography. An icon is a glyph drawn to a stroke grid and sized against the type it sits beside; a picture is a raster or a scene with its own intrinsic ratio and load cost. If the asset has a stroke weight, it is iconography. Two more edges: how long an image may take before its placeholder becomes a loading state is ui-states, and the dimming ratio a photograph takes in the dark theme is dark-mode.

Work inside whatever image pipeline already exists. Look for next/image, Astro's <Image>, @nuxt/image, an image CDN (Cloudinary, imgix, Vercel's optimizer), or a plain <img> convention. Hand-writing srcset beside a framework component that generates it produces two competing sources of truth and one of them will rot. If the project has no pipeline, say so explicitly before adding one — that is a dependency decision, not an image decision.

Quick Reference

You need Open
Format choice, srcset and sizes, lazy versus priority, SVG hygiene, the placeholder ladder references/formats-and-loading.md — open it before writing any <img> or <picture> markup.
Sizes, shapes, fallback chain, stacked groups, presence dots references/avatars.md — open it the moment a person, team, or account is represented by a picture.

Core Principles

  1. Lock the ratio before the bytes arrive. Set aspect-ratio on the box and width/height attributes on the <img>, even when CSS resizes it — the attributes are what let the browser reserve the space during parse. An image without reserved space is a layout shift with a delay fuse. The exception is genuinely unknown intrinsic dimensions at render time, which get a fixed-height container plus object-fit: cover.
  1. One ratio per collection. A grid of 16:9, 4:3, and 3:2 cards reads as broken even though every cell is individually correct, because the eye tracks the gaps between cards, not the cards. Pick one ratio for the surface and crop into it. The exception is masonry, which is explicitly a mixed-ratio format and must therefore be visibly, deliberately masonry.

  2. Choose the placeholder by role, not by duration. Hero and above-the-fold images get a blur-up inlined as a data: URI so it travels in the document itself; grid thumbnails get a single dominant colour; avatars get initials and never a spinner; decorative images get nothing at all. A spinner on an image is always wrong — it promises indeterminate work where the shape is already known. The exception is a batch arriving together, such as a paged-in gallery, which takes one skeleton for the group.

  3. Crop by art direction, not by CSS luck. object-fit: cover on a hero will centre-crop a face out of the frame at narrow widths and nobody will notice until a customer does. Set object-position at minimum; use <picture> with a genuinely different crop when the subject leaves the frame. The exception is user-uploaded content, whose subject you cannot know — square-crop from centre and give the user a way to reposition it.

  4. Every image carries a 1px inset outline: black at 10% in light, white at 10% in dark. Photographs have their own edges, and without a boundary a light-topped image bleeds into a light page. Draw it with outline: 1px solid rgb(0 0 0 / 0.1) and outline-offset: -1px so it costs no layout space. Never a palette neutral (slate, zinc, #111827) and never the accent — a tinted line picks up the surface behind the image and reads as grime along the edge. The exception is a cut-out asset on transparency, where the outline would trace the bounding box instead of the shape.

  5. Screenshots get a second capture, not a filter. Running a UI screenshot through a dark-mode brightness filter produces inverted-looking chrome and grey-on-grey text, and it announces that nobody looked. Capture the app in its dark theme and swap sources with <picture> and prefers-color-scheme. The exception is photographs, which have no dark variant to capture and take the dimming treatment dark-mode defines.

  6. Illustration obeys the icon system's physics. Match illustration stroke weight to the icon set — 2px illustration strokes beside 1px icons read as two different products. Hold one scene to roughly three colours, all from the UI's tokens; recolour any purchased or community pack before it ships. Keep light direction consistent with the UI's shadow direction. Neither icons nor illustrations scale up: a 16px mark blown to 48px keeps its now-spindly stroke and must be redrawn. The exception is a licensed brand asset you are not permitted to alter.

  7. Show product work running, framed, and slowable. A still of an interface proves layout; it proves nothing about behaviour, which is where the work actually is. Put the recording inside a device frame so the viewer knows what they are looking at, and ship a 1x / 0.5x speed toggle — Benji Taylor puts one on every demo on his site, which turns a portfolio piece into something a reader can actually inspect. The exception is when layout genuinely is the subject; then a still is honest.

Smell / Fix

Smell Fix
Page jumps as images load No reserved space — add aspect-ratio plus width/height attributes
Card grid feels ragged though each card is fine Mixed ratios — crop the collection to one
Spinner sitting in an image box Blur-up, dominant colour, or nothing — never a spinner
Faces cropped out at mobile widths object-position, or a second crop via <picture>
Image edges look dirty or smudged Tinted outline — pure black/white at 10% only
Dark theme screenshot looks washed out It is a filtered light capture; take a real dark capture
Stock photo of people at laptops Delete it. Nothing replaces it
Illustration looks bolted on Recolour to tokens, match stroke weight and light direction
Hero image is the LCP and lazy-loaded Remove loading="lazy", add fetchpriority="high"

Output Format

Every image ships this contract — no element leaves with a field missing:

<img
  src="/hero-800.avif"
  srcset="/hero-800.avif 800w, /hero-1600.avif 1600w"
  sizes="(min-width: 768px) 50vw, 100vw"
  width="1600" height="900"
  alt="Order confirmation screen with the receipt expanded"
  decoding="async"
  fetchpriority="high"
  class="-outline-offset-1 outline-1 outline-black/10 dark:outline-white/10"
/>

Decorative images take alt="" — empty, never missing, and never a filename. Below the fold, drop fetchpriority and add loading="lazy".

Checklist

  • Every image has reserved space before load (aspect-ratio + width/height)
  • One aspect ratio per collection, or the layout is deliberately masonry
  • Placeholder chosen by role; no spinners in image boxes
  • Crops verified at the narrowest supported width, not just at desktop
  • 1px inset outline, black/white at 10%, on every non-cut-out image
  • Dark theme has real dark captures for screenshots, not filtered light ones
  • Illustrations match icon stroke weight, token colours, and light direction
  • LCP image is not lazy-loaded and carries fetchpriority="high"
  • Every image has an alt attribute, empty if decorative
  • No stock photography, no generic 3D render, no blob-and-character illustration