Tiles
Tiles are interactive navigation elements that link to content. Unlike Cards which are static content containers, tiles are clickable and use <a> or <button> elements. Use text-tile for icon-and-label layouts or media-tile for image-based navigation.
Text tile
Section titled “Text tile”The text tile is a compact interactive element with an optional icon at the top and a body label anchored to the bottom. The icon is a direct child of the tile — not a slotted element.
When the icon is omitted, space is reserved at the top and the body label stays anchored to the bottom.
import { Icon } from '@volvo-cars/react-icons';
export function TextTile() { return ( <div className="grid-cols-2 gap-x-gutter gap-y-24" style={{ height: '200px' }} > <a href="#top" className="text-tile"> <Icon icon="charging-battery" size={24} /> <span slot="body">Charging</span> </a> <a href="#top" className="text-tile"> <span slot="body">Without icon</span> </a> </div> );}This component uses slots to give content built-in styling.
- Icon – Direct child element (not slotted)
slot="body"– Label text
<a class="text-tile" href="#" style="height: 200px"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24" > <path stroke="currentColor" stroke-width="1.5" d="M12 3v18M3 12h18" /> </svg> <code slot="body">body</code></a>Grid layout
Section titled “Grid layout”Wrap tiles in <li> elements inside a <ul> for semantic grouping. Give the container a fixed height so tiles share consistent dimensions.
import { Icon } from '@volvo-cars/react-icons';
export function TextTileGrid() { return ( <ul className="grid-cols-3 gap-x-gutter gap-y-24" style={{ height: '200px' }} > <li> <a href="#top" className="text-tile"> <Icon icon="charging-battery" size={24} /> <span slot="body">Charging</span> </a> </li>
<li> <a href="#top" className="text-tile"> <Icon icon="calendar" size={24} /> <span slot="body">Service booking</span> </a> </li>
<li> <a href="#top" className="text-tile"> <Icon icon="plus-circled" size={24} /> <span slot="body">Accessories</span> </a> </li> </ul> );}Media tile
Section titled “Media tile”The media tile pairs an image with a body label. The media slot defaults to a 4 / 3 aspect ratio. Images hover-zoom on interaction.
<a href="#" class="media-tile" style="max-width: 360px"> <div slot="media"> <img class="img" src="/images/cars/card/es90.avif" alt="" /> </div> <span slot="body">Explore the Volvo ES90</span></a>This component uses slots to give content built-in styling.
slot="media"– Image containerslot="body"– Label text
<a class="media-tile" href="#" style="max-width: 280px"> <div slot="media" class="bg-feedback-gray flex items-center justify-center h-full" > <code>media</code> </div> <code slot="body">body</code></a>The media slot requires a wrapping <div> — images are absolutely positioned inside it for the hover zoom effect.
Horizontal layout
Section titled “Horizontal layout”Add flex-row items-center gap-16 to arrange the media beside the label. Set a fixed width on the media slot to control its size — the aspect ratio determines the height.
<a href="#" class="media-tile flex-row items-center gap-16" style="max-width: 360px"> <div slot="media" class="aspect-3/2" style="width: 125px"> <img class="img" src="/images/cars/card/es90.avif" alt="" /> </div> <span slot="body">Explore the Volvo ES90</span></a>Grid layout
Section titled “Grid layout”<ul class="grid-cols-3 gap-x-gutter gap-y-24"> <li> <a href="#" class="media-tile"> <div slot="media"> <img class="img" src="/images/cars/thumbnails/ex30-small.avif" alt="" /> </div> <span slot="body">EX30</span> </a> </li>
<li> <a href="#" class="media-tile"> <div slot="media"> <img class="img" src="/images/cars/thumbnails/ex60-small.avif" alt="" /> </div> <span slot="body">EX60</span> </a> </li>
<li> <a href="#" class="media-tile"> <div slot="media"> <img class="img" src="/images/cars/thumbnails/ex90-small.avif" alt="" /> </div> <span slot="body">EX90</span> </a> </li></ul>Accessibility
Section titled “Accessibility”- Always use
<a>for navigation or<button>for actions — tiles must be interactive elements - Provide descriptive
alttext for images, or usealt=""for decorative images when the body label provides sufficient context - Add
aria-hidden="true"to decorative icons that repeat the body label’s meaning - In grid layouts, wrap tiles in
<li>elements inside a<ul>for semantic list structure - The body label is styled with an underline to signal interactivity without relying on color alone
CSS reference
Section titled “CSS reference”| Class | Description |
|---|---|
text-tile | Interactive tile with optional icon and bottom-anchored label. Secondary background. |
media-tile | Interactive tile with image (4:3 cover) and label. Image zooms on hover. |