Bento grid

벤토 그리드

A layout that packs differently sized cells into one tight grid, like compartments in a Japanese bento box.

Also known as: Bento box layout
···
html
<div class="bento" id="bento">
  <div class="tile hero"><span class="dot"></span><i class="ln l1"></i><i class="ln l2"></i></div>
  <div class="tile stat">128</div>
  <div class="tile chart"><b></b><b></b><b></b></div>
  <div class="tile wide"><i class="ln"></i><i class="ln"></i></div>
  <div class="tile sq"></div>
</div>
css
.bento{width:min(90%,560px);aspect-ratio:16/9;display:grid;gap:clamp(6px,1.5vmin,10px);
  grid-template-columns:repeat(4,1fr);grid-template-rows:repeat(3,1fr)}
.tile{border-radius:clamp(8px,1.6vmin,14px);background:var(--surface);border:1px solid var(--line);
  box-shadow:0 2px 8px rgba(0,0,0,.08);display:flex;align-items:center;justify-content:center;gap:6px;
  transition:transform .45s cubic-bezier(.2,.8,.2,1),opacity .35s;overflow:hidden;position:relative}
.hero{grid-area:hero;background:var(--accent);flex-direction:column;align-items:flex-start;padding:10%}
.hero .dot{width:18%;aspect-ratio:1;border-radius:50%;background:#fff;opacity:.9}
.hero .ln{display:block;height:12%;border-radius:3px;background:rgba(255,255,255,.75);margin-top:8%}
.hero .l1{width:70%}.hero .l2{width:45%}
.stat{grid-area:stat;font-size:clamp(16px,4.4vmin,30px);font-weight:800;color:var(--accent-2)}
.chart{grid-area:chart;align-items:flex-end;padding:10%;gap:6%}
.chart b{width:16%;background:var(--accent-3);border-radius:3px 3px 0 0}
.chart b:nth-child(1){height:38%}.chart b:nth-child(2){height:72%}.chart b:nth-child(3){height:54%}
.wide{grid-area:wide;flex-direction:column;align-items:flex-start;padding:8%;gap:10%}
.wide .ln{width:55%;height:14%;border-radius:3px;background:var(--line)}
.sq{grid-area:sq;background:var(--muted);opacity:.3}
.bento.a{grid-template-areas:"hero hero stat chart" "hero hero stat chart" "wide wide wide sq"}
.bento.b{grid-template-areas:"stat wide wide wide" "chart hero hero sq" "chart hero hero sq"}
.bento.c{grid-template-areas:"hero hero hero stat" "wide chart chart stat" "wide chart chart sq"}
.tile.pulse{transform:scale(.92);opacity:.55}
js
const el = document.getElementById('bento');
const layouts = ['a', 'b', 'c'];
let i = 0;
el.classList.add(layouts[0]);
function next() {
  const tiles = el.querySelectorAll('.tile');
  tiles.forEach((t) => t.classList.add('pulse'));
  setTimeout(() => {
    el.classList.remove(layouts[i]);
    i = (i + 1) % layouts.length;
    el.classList.add(layouts[i]);
    tiles.forEach((t) => t.classList.remove('pulse'));
  }, 260);
}
setInterval(next, 2400);

Popularised by Apple's product pages (iPhone, Mac launches) from 2023 onward. Under the hood it is plain CSS Grid — columns defined with grid-template-columns, and each item spans some of them via grid-column/grid-row.

What makes it "bento" rather than a plain grid is sizing cells by the weight of the content: the important card gets 2×2, a minor stat gets 1×1. That lets you mix images, numbers and text on one screen without it feeling cluttered, because size tells you what matters first.

Slice it too finely and the hierarchy collapses — nothing reads as "the" highlight anymore. One or two hero cells plus three to five supporting ones is a good rule of thumb.

When to use

Good for feature overviews or dashboard summaries mixing different kinds of content. If everything has equal weight (a product list), a plain uniform grid is simpler and better.