CardsFree

Basic Bento

4×3 CSS Grid with six asymmetric cells: scale 1.05 and violet glow on hover, spring transition — pure CSS, zero JavaScript.

CSSGridHover
Featured
A
B
Wide
C
D
Hover or click the scene to interact

This effect is free — the Cards category contains 41 effects total, including 6 free. Effect.Labs has 811 vanilla effects. Explore the category →

Usage examples

Monthly revenue
12 480 €
↑ +18 %
Subscribers
1 240
Churn
2,4 %
Trials this week
48
Satisfaction
4,8 / 5
New this month
127

① Dashboard — SaaS metrics tiles

WhenHome screen of a SaaS app or back-office displaying 6 key indicators at a glance.
WhyThe scale + glow on hover signals that each tile is clickable without adding chevrons or visible buttons — the interface stays clean while remaining interactive.
Settingsgap 8px, --bg-card #111827, accent violet kept (#6366f1), cell-1 (2×2) for the main metric (MRR, DAU…).
Built-in AI
Real-time generation and analysis.
🔧
No code
Real-time
🚀 Deploy in 1 click
📊 Advanced analytics
💬 Support 24/7

② Landing page — Product feature grid

WhenA 'What you get' or 'Our features' section mid-page on a dark background.
WhyThe featured cell (2×2) draws the eye to the main feature; the other 5 create a natural visual hierarchy in the Apple bento style. The glow invites exploration without a visible CTA.
Settingsgap 16px, --radius-lg 20px, color gradient as background-image per cell, --border transparent.
Featured project
Visual identity · Maison Lefort
2026
Web design
Motion
UI / UX 12 projects
Illustration 8 projects
Typography 5 projects

③ Portfolio — Project gallery and categories

WhenHome page of a creative studio or freelancer: featured cell for the flagship project, 5 cells for categories.
WhyThe asymmetric grid delivers a modern magazine look; the isolated scale on each project at hover creates clear hierarchy without complex masking animations.
Settingsbackground-size: cover per cell, --bg-card transparent, hover box-shadow with brand color (replace #6366f1).

How it works

The layout is a repeat(4, 1fr) / repeat(3, 1fr) grid with six deliberately asymmetric cells: .cell-1 spans 2 columns × 2 rows via grid-area: span 2 / span 2, .cell-4 through .cell-6 each span two columns (grid-column: span 2), and .cell-2 / .cell-3 each occupy one column. The featured cell naturally draws the eye without ever breaking the Grid flow.

On hover, each cell simultaneously receives a transform: scale(1.05), a z-index: 10 to rise above its neighbors without triggering a layout reflow, a border tint of rgba(99, 102, 241, 0.5), and a box-shadow with 40 px violet diffusion. The spring transition cubic-bezier(0.175, 0.885, 0.32, 1.275) over 0.4 s produces a slight overshoot that makes the cell feel like it leaps toward the viewer.

A pseudo-element ::before at position: absolute; inset: 0 carries a linear-gradient(135deg, rgba(99,102,241,0.1) 0%, transparent 50%). Its opacity transitions from 0 to 1 on hover with a separate 0.3 s transition — the cell's top-left corner gently illuminates, adding depth without impacting render performance.

The effect is pure CSS: the file also includes seven ready-to-use variants — .bento-images, .bento-animated, .bento-interactive, .bento-stats, .bento-reveal, .bento-cardstack, and .bento-responsive. Cells rely on four design-system CSS variables: --bg-card, --radius-lg, --border, and --text-secondary — define or override them inline based on your context.

Accessibility

  • No prefers-reduced-motion in the provided CSS: scale and glow transitions always run regardless of the OS preference. For compliant projects, add @media (prefers-reduced-motion: reduce) { .bento-cell { transition: none; } }.
  • The div.bento-cell elements are plain divs with no tabindex, role, or aria-label: not keyboard-focusable, and the :hover effect is not triggered by Tab or Enter.
  • The container and grid have no ARIA roles in the base HTML — add them to match your semantic use (e.g. role="region" + aria-label).
  • Text contrast depends on the --text-secondary and --bg-card CSS variables defined by your theme — verify the WCAG AA ratio (≥ 4.5:1) in your own context.
  • To make cells keyboard-accessible (links, buttons), add tabindex="0" on each cell and duplicate the :hover rules under :focus-visible.

Browser compatibility

Relies on CSS Grid (grid-template-columns, grid-area: span) and CSS Custom Properties — natively supported since Chrome 57 / Firefox 52 / Safari 10.1. Zero JavaScript dependency.

Chrome 88+✓ Full
Firefox 87+✓ Full
Safari 15+✓ Full
Edge 88+✓ Full
Mobile iOS✓ Full
Android Chrome✓ Full

On IE11 and browsers without CSS Grid, cells fall back to display: block and stack vertically — no JS errors, the page stays readable.

The code

Copy the three blocks into your page. No dependencies.

HTML
<div class="bento-container">
  <div class="bento-grid bento-basic">
    <div class="bento-cell cell-1">Featured</div>
    <div class="bento-cell cell-2">A</div>
    <div class="bento-cell cell-3">B</div>
    <div class="bento-cell cell-4">Wide</div>
    <div class="bento-cell cell-5">C</div>
    <div class="bento-cell cell-6">D</div>
  </div>
</div>
CSS
.bento-container  {
   width: 100%;
   max-width: 600px;
   aspect-ratio: 4 / 3;
   }

.bento-grid  {
   display: grid;
   gap: 12px;
   width: 100%;
   height: 100%;
   }

.bento-cell  {
   background: var(--bg-card);
   border-radius: var(--radius-lg);
   border: 1px solid var(--border);
   display: flex;
   align-items: center;
   justify-content: center;
   font-weight: 600;
   font-size: 0.85rem;
   color: var(--text-secondary);
   position: relative;
   overflow: hidden;
   }

.bento-basic  {
   grid-template-columns: repeat(4, 1fr);
   grid-template-rows: repeat(3, 1fr);
   }

.bento-basic .cell-1  {
   grid-area: span 2 / span 2;
   }

.bento-basic .cell-2  {
   grid-column: span 1;
   }

.bento-basic .cell-3  {
   grid-column: span 1;
   }

.bento-basic .cell-4  {
   grid-column: span 2;
   }

.bento-basic .cell-5  {
   grid-column: span 2;
   }

.bento-basic .cell-6  {
   grid-column: span 2;
   }

.bento-basic .bento-cell  {
   transition: 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275);
   }

.bento-basic .bento-cell:hover  {
   transform: scale(1.05);
   z-index: 10;
   border-color: rgba(99, 102, 241, 0.5);
   box-shadow: rgba(99, 102, 241, 0.3) 0px 20px 40px;
   }

.bento-basic .bento-cell::before  {
   content: "";
   position: absolute;
   inset: 0px;
   background: linear-gradient(135deg, rgba(99, 102, 241, 0.1) 0%, transparent 50%);
   opacity: 0;
   transition: opacity 0.3s;
   }

.bento-basic .bento-cell:hover::before  {
   opacity: 1;
   }

.bento-images .cell-1  {
   grid-area: span 2 / span 2;
   }

.bento-images .cell-2  {
   grid-column: span 2;
   }

.bento-images .cell-3  {
   grid-area: span 2 / span 1;
   }

.bento-images .cell-4  {
   grid-column: span 1;
   }

.bento-images .cell-5  {
   grid-column: span 2;
   }

.bento-images .cell-6  {
   grid-column: span 1;
   }

.bento-images .bento-cell  {
   background-size: cover;
   background-position: center center;
   cursor: pointer;
   }

.bento-images .cell-1  {
   background: linear-gradient(135deg, rgb(102, 126, 234) 0%, rgb(118, 75, 162) 100%);
   }

.bento-images .cell-2  {
   background: linear-gradient(135deg, rgb(240, 147, 251) 0%, rgb(245, 87, 108) 100%);
   }

.bento-images .cell-3  {
   background: linear-gradient(135deg, rgb(79, 172, 254) 0%, rgb(0, 242, 254) 100%);
   }

.bento-images .cell-4  {
   background: linear-gradient(135deg, rgb(67, 233, 123) 0%, rgb(56, 249, 215) 100%);
   }

.bento-images .cell-5  {
   background: linear-gradient(135deg, rgb(250, 112, 154) 0%, rgb(254, 225, 64) 100%);
   }

.bento-images .cell-6  {
   background: linear-gradient(135deg, rgb(161, 140, 209) 0%, rgb(251, 194, 235) 100%);
   }

.bento-images .bento-cell .overlay  {
   position: absolute;
   inset: 0px;
   background: rgba(0, 0, 0, 0.4);
   display: flex;
   align-items: center;
   justify-content: center;
   opacity: 0;
   transition: 0.4s;
   }

.bento-images .bento-cell .overlay span  {
   color: white;
   font-weight: 700;
   font-size: 1rem;
   transform: translateY(20px);
   transition: transform 0.4s;
   }

.bento-images .bento-cell:hover .overlay  {
   opacity: 1;
   }

.bento-images .bento-cell:hover .overlay span  {
   transform: translateY(0px);
   }

.bento-animated .cell-1  {
   grid-area: span 1 / span 2;
   }

.bento-animated .cell-2  {
   grid-area: span 2 / span 1;
   }

.bento-animated .cell-3  {
   grid-area: span 2 / span 1;
   }

.bento-animated .cell-4  {
   grid-column: span 2;
   }

.bento-animated .cell-5  {
   grid-area: span 1 / span 2;
   }

.bento-animated .cell-6  {
   grid-area: span 1 / span 2;
   }

.bento-animated .bento-cell  {
   opacity: 0;
   transform: translateY(30px) scale(0.9);
   animation: 0.6s cubic-bezier(0.16, 1, 0.3, 1) 0s 1 normal forwards running bentoFadeIn;
   }

.bento-animated .cell-1  {
   animation-delay: 0.1s;
   background: linear-gradient(135deg, rgb(99, 102, 241) 0%, rgb(139, 92, 246) 100%);
   }

.bento-animated .cell-2  {
   animation-delay: 0.2s;
   background: linear-gradient(135deg, rgb(236, 72, 153) 0%, rgb(244, 63, 94) 100%);
   }

.bento-animated .cell-3  {
   animation-delay: 0.3s;
   background: linear-gradient(135deg, rgb(6, 182, 212) 0%, rgb(59, 130, 246) 100%);
   }

.bento-animated .cell-4  {
   animation-delay: 0.4s;
   background: linear-gradient(135deg, rgb(16, 185, 129) 0%, rgb(5, 150, 105) 100%);
   }

.bento-animated .cell-5  {
   animation-delay: 0.5s;
   background: linear-gradient(135deg, rgb(245, 158, 11) 0%, rgb(239, 68, 68) 100%);
   }

.bento-animated .cell-6  {
   animation-delay: 0.6s;
   background: linear-gradient(135deg, rgb(139, 92, 246) 0%, rgb(217, 70, 239) 100%);
   }

.bento-animated .bento-cell span  {
   color: white;
   font-weight: 700;
   }

.bento-interactive .bento-cell  {
   cursor: pointer;
   transition: 0.5s cubic-bezier(0.175, 0.885, 0.32, 1.275);
   background: var(--bg-elevated);
   }

.bento-interactive .bento-cell.expanded  {
   z-index: 100;
   background: linear-gradient(135deg, rgb(99, 102, 241) 0%, rgb(139, 92, 246) 100%);
   box-shadow: rgba(99, 102, 241, 0.4) 0px 25px 50px;
   grid-area: span 2 / span 2 !important;
   }

.bento-interactive .bento-cell .expand-icon  {
   width: 30px;
   height: 30px;
   border-radius: 50%;
   background: rgba(99, 102, 241, 0.2);
   display: flex;
   align-items: center;
   justify-content: center;
   transition: 0.3s;
   }

.bento-interactive .bento-cell:hover .expand-icon  {
   background: rgba(99, 102, 241, 0.4);
   transform: scale(1.1);
   }

.bento-interactive .bento-cell.expanded .expand-icon  {
   background: rgba(255, 255, 255, 0.2);
   }

.bento-interactive .bento-cell.expanded .cell-content span  {
   color: white;
   }

.bento-stats .cell-1  {
   grid-area: span 2 / span 2;
   }

.bento-stats .cell-2  {
   grid-column: span 2;
   }

.bento-stats .cell-3  {
   grid-column: span 1;
   }

.bento-stats .cell-4  {
   grid-column: span 1;
   }

.bento-stats .cell-5  {
   grid-column: span 2;
   }

.bento-stats .cell-6  {
   grid-column: span 2;
   }

.bento-stats .bento-cell  {
   flex-direction: column;
   gap: 8px;
   padding: 16px;
   }

.bento-stats .cell-1 .stat-number  {
   font-size: 3rem;
   }

.bento-stats .bento-cell:hover .stat-bar-fill  {
   width: var(--fill-width, 75%);
   }

.bento-reveal .cell-1  {
   grid-area: span 2 / span 2;
   }

.bento-reveal .cell-2  {
   grid-area: span 1 / span 2;
   }

.bento-reveal .cell-3  {
   grid-column: span 2;
   }

.bento-reveal .cell-4  {
   grid-area: span 1 / span 2;
   }

.bento-reveal .cell-5  {
   grid-column: span 2;
   }

.bento-reveal .bento-cell  {
   cursor: pointer;
   background: var(--bg-elevated);
   }

.bento-reveal .bento-cell:hover .reveal-front  {
   opacity: 0;
   transform: scale(1.2);
   }

.bento-reveal .bento-cell:hover .reveal-back  {
   opacity: 1;
   transform: scale(1);
   }

.bento-reveal .bento-cell:hover  {
   border-color: rgba(99, 102, 241, 0.3);
   box-shadow: rgba(99, 102, 241, 0.2) 0px 10px 30px;
   }

.bento-cardstack .cell-1  {
   grid-area: span 2 / span 2;
   }

.bento-cardstack .cell-2  {
   grid-area: span 2 / span 2;
   }

.bento-cardstack .cell-3  {
   grid-column: span 2;
   }

.bento-cardstack .cell-4  {
   grid-column: span 2;
   }

.bento-cardstack .bento-cell  {
   padding: 16px;
   background: var(--bg-elevated);
   }

.bento-cardstack .bento-cell:hover .stacked-card:nth-child(1)  {
   transform: translate(-50%, -50%) translateX(-30%) rotate(-10deg);
   }

.bento-cardstack .bento-cell:hover .stacked-card:nth-child(2)  {
   transform: translate(-50%, -50%) translateY(-5px);
   }

.bento-cardstack .bento-cell:hover .stacked-card:nth-child(3)  {
   transform: translate(-50%, -50%) translateX(30%) rotate(10deg);
   }

.bento-cardstack .bento-cell:hover .mini-card:nth-child(1)  {
   transform: translateY(-10px) rotate(-5deg);
   }

.bento-cardstack .bento-cell:hover .mini-card:nth-child(2)  {
   transform: translateY(-15px);
   }

.bento-cardstack .bento-cell:hover .mini-card:nth-child(3)  {
   transform: translateY(-10px) rotate(5deg);
   }

.bento-responsive .bento-cell  {
   transition: 0.5s cubic-bezier(0.16, 1, 0.3, 1);
   }

.bento-responsive .bento-cell span  {
   color: white;
   font-weight: 600;
   font-size: 0.7rem;
   }

.bento-responsive .bento-cell:hover  {
   transform: scale(1.05);
   z-index: 10;
   box-shadow: rgba(0, 0, 0, 0.3) 0px 15px 30px;
   }

@keyframes bentoFadeIn  {
   
  100%  {
   opacity: 1;
   transform: translateY(0px) scale(1);
   }
}

/* Variables du design system du site, dont ce code depend. Sans elles,
   l'acheteur obtenait des coins carres et des couleurs par defaut (revue Owen).
   Valeurs reprises de css/style.css — a adapter librement. */
.bento-container {
  --bg-card: #12121a;
  --bg-elevated: #1a1a24;
  --border: rgba(255, 255, 255, 0.08);
  --radius-lg: 0.75rem;
  --text-secondary: #a1a1aa;
}
JavaScript (fx-0145)
// Effet CSS pur — pas de JavaScript nécessaire

Customize

Options passed to the API or data-* attributes:

Option / propertyDefaultEffect
--bg-card theme-defined Cell background — set to #1e1e2e for a uniform dark background.
--border theme-defined Border color (1px solid) — rgba(255,255,255,0.08) for a subtle line on dark backgrounds.
--radius-lg theme-defined Cell border-radius — 12px standard, 20px heavily rounded.
--text-secondary theme-defined Text label color — #94a3b8 for soft grey on dark backgrounds.
gap: 12px in .bento-grid 12px Space between cells — 8px for compact, 20px for airy.
rgba(99,102,241,…) in .bento-basic .bento-cell:hover and ::before #6366f1 Glow and overlay color — 3 occurrences to replace with your brand color.
transform: scale(1.05) in .bento-basic .bento-cell:hover 1.05 Hover zoom amount — 1.03 for subtle, 1.08 for pronounced.
transition: 0.4s cubic-bezier(0.175,0.885,0.32,1.275) in .bento-basic .bento-cell 0.4s spring Duration and curve — 0.25s ease-out for a linear feel without overshoot.

FAQ

Does Basic Bento work without JavaScript?

Yes, it is 100% CSS — not a single line of JavaScript. Copy the HTML and CSS and the effect works immediately in any framework (React, Vue, Svelte) or in plain HTML.

How do I change the violet glow color?

The color #6366f1 appears in three places in the CSS: border-color on hover, box-shadow on hover, and the ::before gradient. Replace all occurrences of rgba(99,102,241,…) with your brand color for a consistent theme.

Can I use the other grid variants included in the CSS?

Yes. The CSS includes seven ready-to-use variants: .bento-images (cells with images and text overlay), .bento-animated (entry fadeIn animation), .bento-interactive (expand on click), .bento-stats (metrics), .bento-reveal, .bento-cardstack, and .bento-responsive. Just swap the .bento-basic class on the grid div — the six-cell HTML structure stays the same.