Components / Feedback and display
Image
A picture that never shifts the layout, shows a placeholder while it loads and something sensible when it fails. For a person or an account, use Avatar; for an interface symbol, use Icon.
When to useLink to "When to use"
- Photos, screenshots and illustrations anywhere in a page: give it a
ratioand it holds its space from the first paint. - Thumbnails in a grid: one
ratiofor all,fit="cover"to crop them to the same shape. - Pictures that may be missing: uploads, remote addresses and anything else that can fail gets a fallback instead of a broken-image mark.
- Figures:
captionadds a caption that names the picture.
Use something else when:
- the box holds a video, a map or an embed: AspectRatio
- it is a person, a team or an account: Avatar
- it is a symbol in the interface: Icon
- two pictures are compared: CompareSlider
UsageLink to "Usage"
import { Image } from "@arshad-shah/cynosure";
<Image src="/team.jpg" alt="The team at the 2026 offsite" ratio={16 / 9} radius="card" />
<Image src="/logo.png" alt="" width={120} height={40} />
<Image src={url} alt="Uploaded scan" ratio="4/3" fit="contain" caption="Page 1 of 3" />alt is required. Describe what the picture shows, or pass alt="" when it is decoration: it is then hidden from assistive technology.
With ratio the picture fills a box of that shape, as wide as its container. Without it the picture has its natural size, never wider than its container; pass width and height so its space is reserved before it loads.
Fit and positionLink to "Fit and position"
With a ratio, fit="cover" (the default) fills the box and crops what does not fit, and fit="contain" shows the whole picture. position chooses the part that stays in view, as CSS object-position.
When it failsLink to "When it fails"
The picture is replaced by a quiet box with the image icon and the alt text, in the same space. fallback replaces that box, and onError is still called. Changing src tries again.
CaptionLink to "Caption"
caption wraps the picture in a figure whose name is the caption.
PropsLink to "Props"
| Prop | What it does | Type | Default |
|---|---|---|---|
srcRequired | Address of the picture. Changing it loads the new picture, also after a failure. | string | |
altRequired | What the picture shows, for people who cannot see it. "" marks it decorative and hides it from them. | string | |
srcSet | Candidate files for different screen densities or widths, as on <img>. | string | |
sizes | With srcSet: how wide the picture is shown, as on <img>. | string | |
width | Natural width in pixels. With height and no ratio, it reserves the picture's space before it loads. | number | |
height | Natural height in pixels. | number | |
ratio | Width divided by height of the box the picture fills (16 / 9, "4/3"), kept at any width with AspectRatio. Without it the picture has its natural size, no wider than its container. | string | number | |
fit | With ratio: cover fills the box and crops, contain shows the whole picture. Default "cover". | "cover" | "contain" | "cover" |
position | With ratio: which part stays in view when cropped, as CSS object-position ("top", "20% 80%"). | string | |
radius | Rounds the corners from the radius tokens. Default "none". | AspectRatioRadius | "none" |
loading | lazy waits until the picture is near the screen; eager loads it at once. Default "lazy". | "lazy" | "eager" | "lazy" |
placeholder | Shown while the picture loads, in place of the Skeleton. | ReactNode | |
fallback | Shown when the picture fails, in place of the box with an icon and the alt text. | ReactNode | |
caption | A caption under the picture: wraps it in a figure named by the caption. | ReactNode | |
onLoad | Called when the picture has loaded. | ((event: SyntheticEvent<HTMLImageElement>) => void) | |
onError | Called when the picture fails to load. The fallback is shown as well. | ((event: SyntheticEvent<HTMLImageElement>) => void) | |
className | Added to the root element (the figure when there is a caption), for layout. | string | |
style | Layout only (width, margin, placement), on the root element. Restyle through --cy-image-* tokens. | CSSProperties |
Generated from the type definitions in @arshad-shah/cynosure 0.5.0.
Behaviour and accessibilityLink to "Behaviour and accessibility"
| Situation | Result |
|---|---|
| Before the picture has loaded | A Skeleton (or placeholder) covers the box; the box already has its final size |
| The picture loads | The placeholder goes, the picture fades in, onLoad is called. Nothing moves |
| The picture fails | The fallback takes its place in the same box, onError is called |
src or srcSet changes | Loading starts again, also after a failure |
| The picture finished before React attached (cached, or in the server's HTML) | It is shown, or its fallback is, without waiting for an event. For a picture in the server's HTML the event has passed, so onLoad and onError are not called |
- Name: the
imghas thealttext as its name. Withalt=""nothing has the image role. - Fallback: the default fallback shows the
alttext on screen, so it is read as text. For a decorative picture it shows only the icon and is hidden from assistive technology. A customfallbackis shown as it is: give it its own text. - Placeholder: the Skeleton is hidden from assistive technology and stops moving under reduced motion.
- Loading:
lazyby default, so pictures far below the screen wait. Useloading="eager"for a picture at the top of the page.decodingisasync. - Root element: with a
ratioor acaptionit is a block as wide as its container (adivor afigure), so keep it out of paragraphs. Otherwise it is an inlinespanthe size of the picture. - Ref: the
imgelement. There is none while the fallback is shown. - Native behaviour: dragging and the context menu are the browser's own.
- Right-to-left: nothing changes. Pictures are not mirrored and
positionis physical, as in CSS.
TouchLink to "Touch"
Nothing in Image can be pressed. To make a picture a link or a button, put it inside Link or a control with a hit area of its own.
ThemingLink to "Theming"
Tokens: --cy-image-radius (the corners of every Image, whatever its radius prop says), --cy-image-fallback-background, --cy-image-fallback-color, --cy-image-caption-gap and --cy-image-caption-color. The placeholder is themed through the Skeleton tokens.
createTheme({ components: { image: { radius: "8px", captionGap: "4px" } } });className and style are for layout only (width, margin, placement).
RelatedLink to "Related"
AspectRatio · Skeleton · Avatar · CompareSlider · Card
These examples run Cynosure 0.5.0 (commit 50ce30b), the version on npm.