Cards✨ Premium

Responsive Bento

CSS auto-fit/dense grid: multi-span cells elegantly reorganize when the container shrinks — zero JavaScript.

CSSResponsiveAuto-fit

You'll get access to the interactive demo with a free account.

This effect is part of Effect.Labs — 811 vanilla effects, some free, some premium. Cards has 41 effects, including 6 free. Explore the category →

3 usage examples

Analytics dashboard — Multi-format KPI view — Responsive Bento example 1

① Analytics dashboard — Multi-format KPI view

WhenAn admin or SaaS dashboard needs to display metrics of varying sizes — a large chart tile, wide secondary metrics, and compact indicators — across any screen resolution.
Whyauto-fit/dense ensures no tile is ever stranded in an empty row: the layout stays structured from 1 200 px down to 320 px without a single explicit media query.
Settingsminmax(80px, 1fr) for columns, grid-auto-rows: 60px, gap: 12px. Main tile as cell-large with a large key figure; secondary metrics as cell-small. Remove resize: horizontal in production.
Project gallery — Async creative portfolio — Responsive Bento example 2

② Project gallery — Async creative portfolio

WhenA portfolio or e-commerce gallery where some projects deserve a featured (large) tile and others a standard one, without defining per-project media queries.
WhyThe dense algorithm recalculates the optimal order at each column jump: the featured project stays visually dominant at every width, and secondary tiles fill the gaps automatically.
Settingsminmax(120px, 1fr) for slightly larger tiles, grid-auto-rows: 80px, background-size: cover on each cell. Distinct gradient colors per category.
Landing page — Product feature grid — Responsive Bento example 3

③ Landing page — Product feature grid

WhenA Features section on a SaaS landing page presenting 8 features: one hero feature (large), two secondary features (wide/tall), and four simple tiles.
WhyAt full width (5–6 columns), the visual hierarchy is immediate; on mobile at 2 columns, the dense algorithm pulls small tiles up under the large one with no visible gap.
Settingsminmax(100px, 1fr), grid-auto-rows: 70px. Different gradient per feature family. Icon + short label in each cell-small.

How it works

The core property is grid-template-columns: repeat(auto-fit, minmax(80px, 1fr)) on .bento-responsive. The CSS engine calculates how many 80 px columns fit in the available width: when space for one column disappears, all columns widen at once and every cell recalculates its position — no JavaScript, no media queries.

grid-auto-flow: dense activates the dense packing algorithm: when a multi-span cell (2×2, 2×1, or 1×2) leaves a hole, the browser slides in the next smaller cell from the DOM. The layout stays compact at every width.

Three span classes declare each tile's footprint: .cell-large with grid-area: span 2 / span 2, .cell-wide with grid-column: span 2, and .cell-tall with grid-row: span 2. The transition: .5s cubic-bezier(.16, 1, .3, 1) makes the position jump visible when the column count changes.

The container has resize: horizontal and overflow: auto for the demo: the user drags the bottom-right handle and watches the reorganization live. In production, remove those two properties — the grid adapts to its parent's width on its own.

Accessibility

  • No prefers-reduced-motion: the code contains no @media (prefers-reduced-motion: reduce) block. The CSS transition always fires on reflow. Add one in production: @media (prefers-reduced-motion: reduce) { .bento-responsive .bento-cell { transition: none } }.
  • Text contrast: var(--text-secondary) (#a1a1aa) on var(--bg-card) (#12121a) → ratio ≈ 7.5:1, WCAG AA compliant (4.5:1 threshold for body text).
  • No interactive elements inside the grid — no focus-trap, no keyboard navigation issues for this static component.
  • The resize: horizontal handle is mouse-only, not keyboard-accessible. In production, let the container follow its parent and test with DevTools or window resizing.
  • No role or aria-label on the grid. For semantic content, add role="list" on .bento-grid and role="listitem" on each .bento-cell.

Browser compatibility

Requires CSS Grid with auto-fit and minmax — available in all modern browsers since 2017.

Chrome 57+✓ Full
Firefox 52+✓ Full
Safari 10.1+✓ Full (no resize handle)
Edge 16+✓ Full
Mobile iOS✓ Full (no handle)
Android Chrome✓ Full (no handle)

Without CSS Grid support, cells render in normal block flow — no JS errors, the page stays readable. The resize: horizontal handle is ignored by Safari and all mobile devices; the grid still adapts through its natural container width.

The code

HTML structure to paste into your page (CSS + JS available with a premium account):

index.html — structure
<div class="bento-responsive-container">
  <div class="bento-grid bento-responsive">
    <div class="bento-cell cell-large">…</div>
    <div class="bento-cell cell-wide">…</div>
    <div class="bento-cell cell-tall">…</div>
    <div class="bento-cell cell-small">…</div>
    <div class="bento-cell cell-small">…</div>
    <div class="bento-cell cell-wide">…</div>
    <div class="bento-cell cell-small">…</div>
    <div class="bento-cell cell-small">…</div>
  </div>
  <span class="resize-hint">Resize</span>
</div>
🔒 Unlock the full code — from €2.99 the first month

Full HTML + CSS + JS, copy-paste ready — with hundreds of premium effects.

Customize

Options passed to the API or data-* attributes:

Option / propertyDefaultEffect
minmax(80px, 1fr) 80px Minimum column width before auto-fit recalculates. Increase (e.g. 120px) for wider tiles and fewer columns; decrease for a denser mosaic effect. Edit inside the .bento-responsive rule.
grid-auto-rows: 60px 60px Height of each row unit. Increase for taller tiles — cell-large (2 rows) and cell-tall (2 rows) scale proportionally.
gap: 12px 12px Spacing between tiles. Reduce to 8px for a tighter look, increase to 20px for an airy premium layout.
transition: .5s cubic-bezier(.16, 1, .3, 1) .5s Duration and easing of the position change on reflow. Shorten to .2s for a snappy jump, or remove the line for an instant reposition.
--bg-card #12121a Background of neutral tiles (cell-small without a gradient). Replace with your brand color or a slightly elevated page background tint.
--border rgba(255,255,255,0.08) Tile border color. Increase opacity (0.15–0.2) for more definition, or switch to a solid color for a design accent.
grid-area: span 2 / span 2 cell-large Edit the spans in .cell-large, .cell-wide, and .cell-tall to create custom formats (e.g. span 3 / span 1 for a very tall 3-row tile).

FAQ

No — resize: horizontal and overflow: auto on the container are a demo feature for dragging the handle and watching the live reflow. In production, remove both properties and let the container follow its parent's width: the auto-fit grid adapts on its own. To test, just resize the browser window or use DevTools responsive mode.
auto-fit recalculates the column count all at once at each threshold: all cells reposition simultaneously. The dense algorithm then picks the best available slot, which may differ from the previous layout. To pin a key tile's position, give it a named grid-area (e.g. grid-area: hero) instead of a plain span.
Yes — each .bento-cell is a standard flex container. Add background-image with background-size: cover for a photo, or insert any component (chart, card, video). The effect is 100% vanilla CSS: it works in React, Vue, Svelte, and Angular without modification.