Core · Media
Image
Shows a picture in a frame of fixed shape, on a flat surface while it loads or when it is missing.
Example
A picture in its frame, then the frame with no picture, then the ratios on offer.
Ratios: 16:9, --4x3, --3x2, --1x1, --21x9, --9x16.
Known issues
If an image fails to load, some browsers add a broken-image icon next to its alt text. In forced-colors mode the surface takes the page's colour, and the frame shows a thin border instead.
Code
Copy the markup
<div class="luz-image">
<picture>
<source type="image/avif" srcset="dunes-640.avif 640w, dunes-1280.avif 1280w" sizes="(min-width: 768px) 50vw, 100vw">
<source type="image/webp" srcset="dunes-640.webp 640w, dunes-1280.webp 1280w" sizes="(min-width: 768px) 50vw, 100vw">
<img src="dunes-1280.jpg" srcset="dunes-640.jpg 640w, dunes-1280.jpg 1280w" sizes="(min-width: 768px) 50vw, 100vw"
width="1280" height="720" alt="Sand dunes under a low sun" loading="lazy" decoding="async">
</picture>
</div>
Variants and options
One modifier sets the shape. Without one, the frame is 16:9.
| Class | Ratio |
|---|---|
.luz-image | 16:9 |
.luz-image | 4:3 |
.luz-image | 3:2 |
.luz-image | Square |
.luz-image | 21:9, for wide banners |
.luz-image | 9:16, portrait |
How it works
A <div> of fixed aspect ratio around a native <picture>, styled by @luz-ds/core. No JavaScript.
- The image fills the frame and is cropped to it.
- The frame is a flat
--luz-surface-strongsurface: with no image, while an image loads, or when it fails. A failed image's alt text is drawn on it, and transparent PNG and SVG images sit on it too. - LUZ ships no placeholder picture: the page asks for nothing it did not name.
Without JavaScript
Nothing changes: the frame and the image are HTML and CSS. Without CSS the image shows at its own size.
Keyboard and ARIA
The frame has no interaction of its own.
- Screen readers announce the
<img>by its alt text; an empty frame announces nothing. - Do not add a role or an
aria-labelto the frame. - If the image is a link, the link takes its name from the alt text, which must then say where it goes.
Contrast and focus are in the Design tab.
Design
When to use
Use the image frame for a picture in a box of fixed shape, such as a card cover or an article header, when the picture may be missing.
- Content from people or from a content system.
- A page built before its images exist.
When not to use
Do not use it for an image that must keep its own shape, such as a chart or a screenshot: the frame crops it.
- For a chart or a diagram with a caption, use a figure.
- For icons and logos, use an
<img>or an SVG at its own size. - Never let an empty frame stand in for an image that carries information: if it is missing, say so in text.
Do and don't
Writing the content
Give every real image an alt text that says what it shows, in one plain sentence.
- Use
alt=""when the image is decorative, or the text next to it already says the same. - The frame crops: keep text and essential detail away from the edges, and describe what stays visible.
- Set
widthandheightto the image's own size, so the page does not jump while it loads. - Add
loading="lazy"only below the fold; an image visible when the page opens should load at once. - Do not put text in images.
Contrast and focus
The frame is the strong surface; if an image fails to load, its alt text shows in primary text on it.
| Part | Colour on background | Light | Dark | High contrast | Needs |
|---|---|---|---|---|---|
Alt text of a broken image | --luz-text-primary on --luz-surface-strong | 13.5:1 | 10.9:1 | 18.0:1 | 4.5:1 |
Measured from the token values of each mode, rounded down. Needs is the WCAG 2.2 AA minimum: 4.5:1 for text, 3:1 for focus rings, borders and icons.
- Focus: the frame takes none.
- Images: their own colours are yours.
Tokens it uses
The 3 tokens that components/image.css reads, by family. Each family links to its page, with the values in every mode. In Figma they are variables with the same names: see Tokens in Figma.
- Radius
--luz-radius-md
Keyboard and ARIA are in the Code tab.
