Bento Grid
A bento grid is a feature showcase where cells claim different amounts of space, so the eye gets a hierarchy instead of a uniform matrix. Use it when your features are genuinely unequal — one headline capability, a few supporting ones.
When every feature carries the same weight, feature grid is still the right answer. A bento that says everything is important says nothing.
Ship accessible UI by default
Every component arrives with its keyboard model, focus handling and ARIA wiring already correct — not as an option you remember to enable.
Theme with tokens
One file changes the whole surface.
No build step
Require it and start composing.
Dark mode is not a fork
Every token switches together, so there is no second set of components to maintain.
MIT licensed
Commercial use, no fee.
Responsive to its own width
The grid reflows on its own width, not the window's — it is a container query. Drag the divider below: as the bento panel narrows, the cells collapse to a single stacked column, and they claim their spans again once the panel is wide enough. A bento in a sidebar, a card, or a split view adapts to the room it actually has.
Reflows to its own width
One column when narrow — whatever the window does.
Container query
Not the viewport.
Pure CSS
No JavaScript reflow.
Any container
A sidebar, a card, a split view — it adapts to the room it has.
Drag the divider ←
Widen or narrow the bento and watch it reflow.
Spans
A cell claims space with span. The claim engages once the grid is wide
enough — in a narrow grid every cell is full width, whatever its span says.
That collapse is not a convenience. A two-column cell inside a cramped grid squeezes its neighbors into unreadable slivers, and because the reflow follows the grid's own width, it happens wherever the grid is narrow — a sidebar, a split view, a phone — not only on a small window.
span |
Claims | Use it for |
|---|---|---|
1x1 |
One cell (default) | A supporting feature |
2x1 |
Two columns wide | A feature that needs a sentence, not a phrase |
1x2 |
Two rows tall | A tall visual — a screenshot, a phone mockup |
2x2 |
Two by two | The one headline capability |
<x-wirekit::bento-grid label="Platform features">
<x-wirekit::bento-cell span="2x2" emphasis>The headline</x-wirekit::bento-cell>
<x-wirekit::bento-cell>A supporting point</x-wirekit::bento-cell>
<x-wirekit::bento-cell span="2x1">Something that needs room</x-wirekit::bento-cell>
</x-wirekit::bento-grid>
Reading order is DOM order There is deliberately no prop to place a cell at an arbitrary track. Such a prop lets the visual order and the order a screen reader announces drift apart — and the drift is invisible to whoever authored it. Write the cells in the order they should be read, and the layout follows.
Emphasis
emphasis lifts a cell with a border and a surface — two independent signals,
so the emphasis survives a reader who cannot separate the accent hue from the
surrounding surface.
<x-wirekit::bento-cell span="2x2" emphasis>The one that matters</x-wirekit::bento-cell>
Bleeding imagery
bleed drops the cell's padding so content can run to the edge — for a
screenshot or an illustration that should meet the border rather than sit in a box.
The cell clips it to its own rounded corners.
<x-wirekit::bento-cell span="1x2" bleed>
<x-wirekit::image src="/img/editor.png" alt="The editor in dark mode" ratio="3/4" fit="cover" />
</x-wirekit::bento-cell>
Props
<x-wirekit::bento-grid>
| Prop | Type | Default | Description |
|---|---|---|---|
label |
string|null |
null |
Accessible name for the showcase. Omit and no group boundary is announced. |
gap |
string |
'md' |
none, xs, sm, md, lg, xl, 2xl — the same ladder as grid. |
scope |
string|null |
null |
Class-scope override. |
<x-wirekit::bento-cell>
| Prop | Type | Default | Description |
|---|---|---|---|
span |
string |
'1x1' |
1x1, 2x1, 1x2, 2x2. Engages from md up. |
emphasis |
bool |
false |
Lift the cell with a border and a surface. |
bleed |
bool |
false |
Drop the cell's padding so content meets the edge. |
scope |
string|null |
null |
Class-scope override. |
Accessibility
- Pass
labeland the showcase becomes a namedrole="group", so a screen reader gets a boundary and a name rather than a run of loose headings. Without a label no group is announced — a boundary that cannot say what it is for is noise. - Reading order is DOM order. Nothing here can reorder cells visually.
emphasisis never color alone: the border and the surface both change.- Rows size to their content, so a tall cell cannot crop the text inside it.
Keyboard Interaction
None of its own. A bento grid is a layout — whatever you put in a cell keeps its own keyboard behavior, in the order the cells are written.