Image
Click to look closer.
About
Image with a hover veil and a click-to-preview lightbox: the caption and the zoom, rotate and close tools sit in a bar over a dark scrim, and the picture pans in the area under it. For receipts, attached documents and team photos. Set no-preview for a plain framed picture.
Usage
Basic
The frame is a button named "Preview:" plus the caption or alt. Hovering shows the navy veil; a click opens the lightbox with zoom, rotate and close on a deep navy scrim, and the caption repeats under it.
Sizes and fit
width and height take a number of px or any CSS length. cover crops to fill the frame; contain fits the whole picture inside it, which a portrait receipt in a landscape frame needs.
Preview source
preview-src is what the lightbox enlarges when the frame should show something smaller: a thumbnail in the list, the full scan on demand. The frame keeps src, and a preview source that fails is reported through suiError and leaves the frame a plain picture.
Plain image
no-preview renders the frame with no veil, no button and no lightbox.
Controlled lightbox and events
open is a mutable, reflected prop; suiOpen fires when the user opens the lightbox. suiClose is cancelable and names its reason, so a stray scrim click can be vetoed while Escape and the close control still work.
A source that fails
The error slot replaces a picture that fails, as on the first frame. With the slot empty the frame shows the image glyph and "Image unavailable" on its well, as on the second. suiError reports the source, and the frame stops being a preview button, because there is nothing to enlarge.
Keyboard
| Key | Action |
|---|---|
| Enter Space | On the frame, opens the lightbox. On a tool, presses it. |
| Tab | Moves through the zoom, rotate and close tools. Focus stays inside the lightbox while it is open. |
| Arrow keys | Pan the enlarged picture once it is zoomed past 1x. |
| Escape | Closes the lightbox and returns focus to the frame. Only the topmost open modal answers it. |
API
<sui-image>
Properties
| Property | Attribute | Type | Default | Description |
|---|---|---|---|---|
alt | alt | string | '' | Alt text. Also names the lightbox when there is no caption. |
caption | caption | stringstring | undefined | Caption under the image (11.5px faint ink) and under the lightbox preview. | |
fit | fit | SuiImageFit"contain" | "cover" | 'cover' | How the picture fills the frame: cover crops to fill it, contain fits the whole picture inside it. A portrait receipt in a landscape frame loses its top and bottom under cover. Unknown values fall back to cover. |
height | height | number | string | undefined | Frame height: a number of px or any CSS length. | |
loading | loading | SuiImageLoading"eager" | "lazy" | 'lazy' | Native loading hint for the framed picture. lazy by default, because the shape this element is for is a list of attachments. The enlarged preview always loads eagerly, because the user asked for it. Unknown values fall back to lazy. |
noPreview | no-preview | boolean | false | Turns the preview off, for a plain framed picture. By default the frame is a button: hovering shows the navy veil with a zoom glyph, and a click, Enter or Space opens the lightbox. With no-preview there is no veil, no button and no lightbox. |
open | open | boolean | false | Shows the lightbox. Mutable; the element opens it on click and closes it on Escape, the scrim and the close control. Focus is trapped inside while it is open and returns to the frame afterwards. Zoomed past 1x, the picture drags to pan and the arrow keys pan it too. While open, and while it fades out, the lightbox paints in the browser's top layer, so a transformed or clipping ancestor cannot trap it; everything outside it is inert and the page does not scroll, and a node the page adds outside it while it is open goes inert too. The lightbox is role="dialog" with no aria-modal, so VoiceOver keeps reading the toast region; Tab goes on from the lightbox into the toast stack and back. An element the page marks data-sui-keep-live stays usable with everything in it, and focus may move into it and back. |
previewSrc | preview-src | stringstring | undefined | Source for the enlarged preview, when it should not be src: a full-resolution scan behind a small framed thumbnail, so a list of fifty receipts downloads fifty thumbnails and the one scan the reader opens. Falls back to src. If it fails to load the preview withdraws itself and the frame stops being a preview button, while the framed picture stays. | |
radius | radius | stringstring | undefined | Frame corner radius (default var(--radius-lg)). | |
src* | src | string | Image source. | |
width | width | number | string | undefined | Frame width: a number of px or any CSS length. |
Events
| Event | Detail | React | Vue | Description |
|---|---|---|---|---|
suiClose | SuiCloseReason"cancel" | "close-button" | "escape" | "outside" | "pick" | "scrim" | "trigger" | onSuiClose | @sui-close | Fires before the lightbox closes itself; detail is 'escape' | 'scrim' | 'close-button', or 'cancel' when the source failed while the preview was open. Cancelable: preventDefault() keeps it open. It does not bubble. The corner X is always there: unlike sui-dialog there is no hide-close, and that is a decision rather than a gap. A dialog may force a choice and a message may be permanent, so those two let the page leave the control out (hide-close, and closable left unset). A lightbox covers the page, so a copy of it with no visible way out is a trap and not a configuration. Cancel the event instead if a close has to be refused. |
suiError | string | onSuiError | @sui-error | Fires when src or previewSrc fails to load; detail is the source that failed. A failed src is replaced by the error slot, or, with nothing in it, by the image glyph and "Image unavailable" on the frame's well, as the galleria and the image compare draw theirs. Either failure leaves the frame a plain picture rather than a preview button, because there is nothing to enlarge. Does not bubble. |
suiOpen | void | onSuiOpen | @sui-open | Fires when the user opens the lightbox. It does not bubble. |
Methods
| Method | Signature | Description |
|---|---|---|
setFocus() | setFocus() => Promise<void> | Moves focus to the frame, the preview button. A plain picture (no-preview, or a source that failed) has no tab stop and keeps focus where it is. The host's own focus() does the same. |
Slots
| Slot | Description |
|---|---|
error | Shown in place of the picture when src fails to load. Empty by default. |
Types
SuiCloseReason typeWhy a dismissible surface is closing. Detail of the cancelable suiClose. A consumer expresses "a stray backdrop click must not close this" by calling preventDefault() on the reason it does not accept, which is why none of these needs a prop of its own. | |||
|---|---|---|---|
| No members. |
SuiImageFit typeHow the picture fills its frame. | |||
|---|---|---|---|
| No members. |
SuiImageLoading typeNative loading hint for the framed picture. | |||
|---|---|---|---|
| No members. |
Theming
Every design token this element can render with, read from its own stylesheets and the ones it imports. Set a token on :root or on any ancestor and every use below follows it. The values shown are the ones in the theme you are viewing. The list is read per stylesheet, so an element that imports a shared drawing module lists that module's tokens too, whether or not it paints with all of them.
Color8
Typography1
Spacing and size1
Radius2
Elevation1
Motion4
Every name above is listed with its value and its role in Foundations.