벤토 그리드

Bento grid

일본 도시락(벤토)처럼 크기가 다른 칸들을 하나의 격자 안에 빈틈없이 채워 넣는 레이아웃.

다른 이름: 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);

Apple이 제품 소개 페이지(예: iPhone, Mac 발표 페이지)에서 즐겨 쓰면서 2023년 이후 널리 퍼진 이름입니다. 기본은 그냥 CSS Grid입니다 — `grid-template-columns`로 칸을 나누고, 항목마다 `grid-column`·`grid-row`로 몇 칸을 차지할지 정합니다.

일반 그리드와 다른 점은 "정보의 무게"에 따라 칸 크기를 다르게 준다는 것입니다. 중요한 카드는 2×2, 보조 지표는 1×1처럼요. 그래서 한 화면에 여러 종류의 콘텐츠(이미지, 숫자, 텍스트)를 섞어도 산만하지 않고 위계가 보입니다.

칸이 너무 잘게 쪼개지면 오히려 어디를 봐야 할지 몰라 위계가 무너집니다. 보통 한 화면에 하이라이트 1~2개, 보조 칸 3~5개 정도가 적당합니다.

언제 쓰나

기능 소개, 대시보드 요약처럼 성격이 다른 콘텐츠를 한 화면에 모아야 할 때. 콘텐츠가 다 똑같은 무게면(예: 상품 목록) 그냥 균일한 그리드가 낫습니다.