Overlay
A contextual scrim anchored to a media element, for presenting info/actions specific to what's behind it (a caption on a photo, a "Play" button on a video thumbnail, hover actions on a gallery grid item).
Real use · caption scrim, always visible
Placement · top / bottom / full
reveal="hover" · gallery grid, scrim fades in on hover/focus
Using Overlay
Silica ships one design system through three paths. They share a class vocabulary but are not interchangeable — pick the one that matches what you are building.
Plain HTML — CSS classes
The Tailwind v4 plugin. Works in any framework or none — Rails, Django, PHP, Go, a static file. This path is complete for Overlay — it needs no JavaScript, so the classes below are the whole story.
/* in your CSS */
@import "tailwindcss";
@plugin "@wizeworks/silicaui";Root class overlay, with 1 modifier:
.overlay.overlay-scrim
React
Typed components over those same classes, with behavior and accessibility from Base UI.
npm i @wizeworks/silicaui-reactimport { Overlay } from "@wizeworks/silicaui-react";Props
| Prop | Type | Required | Description |
|---|---|---|---|
| placement | OverlayPlacement | no | Where the scrim sits over the media. Default "bottom". |
| reveal | OverlayReveal | no | "always" (default) shows the scrim outright; "hover" fades it in on hover/focus. |
| overlay | React.ReactNode | yes | The scrim's content — a caption, badges, action buttons, …. |
| children | React.ReactNode | yes | The underlying media — an <img>, <video>, or any element to scrim over. |
Source of the demo above
The exact file that renders the examples above, so it can never drift from them. It imports a few of this site’s own layout helpers (../lib/…), so read it for the component calls rather than copying it whole.
Show source
import { Overlay, Badge, Button } from "@wizeworks/silicaui-react";
import { Section, Row } from "../lib/Section";
function placeholder(label: string, from: string, to: string): string {
return `data:image/svg+xml,${encodeURIComponent(
`<svg xmlns='http://www.w3.org/2000/svg' width='400' height='260'>` +
`<defs><linearGradient id='g' x1='0' y1='0' x2='1' y2='1'>` +
`<stop offset='0' stop-color='${from}'/><stop offset='1' stop-color='${to}'/>` +
`</linearGradient></defs>` +
`<rect width='400' height='260' fill='url(#g)'/>` +
`</svg>`,
)}`;
}
export function OverlayDemo() {
return (
<>
<Section title="Real use · caption scrim, always visible">
<div className="max-w-sm">
<Overlay
className="rounded-box"
overlay={
<div>
<h3 className="text-base font-semibold">Mountain sunrise</h3>
<p className="text-sm opacity-80">Banff National Park</p>
</div>
}
>
<img src={placeholder("1", "#0ea5e9", "#1e3a8a")} alt="" />
</Overlay>
</div>
</Section>
<Section title="Placement · top / bottom / full">
<Row>
{(["top", "bottom", "full"] as const).map((placement) => (
<div key={placement} className="w-48">
<Overlay
className="rounded-box"
placement={placement}
overlay={<Badge color="primary">{placement}</Badge>}
>
<img src={placeholder(placement, "#f97316", "#7c2d12")} alt="" />
</Overlay>
</div>
))}
</Row>
</Section>
<Section title="reveal="hover" · gallery grid, scrim fades in on hover/focus">
<div className="grid max-w-md grid-cols-3 gap-2">
{["10b981-06b6d4", "8b5cf6-ec4899", "f59e0b-ef4444"].map((pair, i) => {
const [from, to] = pair.split("-").map((c) => `#${c}`);
return (
<Overlay
key={pair}
className="rounded-field"
reveal="hover"
placement="full"
overlay={
<Button size="sm" color="primary">
View
</Button>
}
>
<img src={placeholder(`g${i}`, from!, to!)} alt="" />
</Overlay>
);
})}
</div>
</Section>
</>
);
}Vanilla — node tree to HTML
Overlay — pure CSS ([data-reveal="hover"]:hover .overlay-scrim); no behavior at all (confirmed this pass). Build a node tree, project it with toHtml(), and let the zero-dependency runtime hydrate it. This is the path for generated or user-authored documents — a site builder, CMS output, a static export.
npm i @wizeworks/silicaui-html @wizeworks/silicaui-behaviorsimport { atom, toHtml } from "@wizeworks/silicaui-html";
const node = atom("Overlay", "overlay", { /* props */ }, [/* children */]);
const markup = toHtml(node);Styling on this path is the class string in the second argument — the same classes as the Plain HTML section above. There is no color prop here; write "overlay overlay-primary" rather than passing a colour as a prop.
- Takes children
- yes
- Hydrated by
- nothing — this one is static markup
The full API for Overlay, on every path, is available through the Silica MCP server.