Bento UI
Grid-based bento box layouts with asymmetric cards, rounded corners, and clean modular sections — inspired by Apple's product pages.
MCP
Code
:root {
--bg-body: #0a0a0a;
--bg-card: rgba(255, 255, 255, 0.04);
--bg-card-hover: rgba(255, 255, 255, 0.07);
--border: rgba(255, 255, 255, 0.08);
--border-hover: rgba(255, 255, 255, 0.14);
--text: rgba(255, 255, 255, 0.92);
--text-muted: rgba(255, 255, 255, 0.5);
--text-dim: rgba(255, 255, 255, 0.3);
--accent: #6366f1;
--accent-light: #818cf8;
--green: #22c55e;
--radius: 20px;
--radius-sm: 12px;
--font: "Inter", system-ui, sans-serif;
}
*,
*::before,
*::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
font-family: var(--font);
background: var(--bg-body);
color: var(--text);
min-height: 100vh;
overflow-x: hidden;
}
/* ── Page ── */
.page {
max-width: 680px;
margin: 0 auto;
padding: 48px 24px 64px;
display: flex;
flex-direction: column;
gap: 32px;
}
/* ── Header ── */
.header {
text-align: center;
}
.header__pill {
display: inline-block;
font-size: 11px;
font-weight: 600;
letter-spacing: 0.1em;
text-transform: uppercase;
color: var(--accent-light);
background: rgba(99, 102, 241, 0.1);
border: 1px solid rgba(99, 102, 241, 0.25);
padding: 5px 14px;
border-radius: 100px;
margin-bottom: 20px;
}
.header__title {
font-size: clamp(40px, 10vw, 72px);
font-weight: 800;
line-height: 1;
letter-spacing: -0.04em;
color: var(--text);
}
.header__title span {
color: var(--accent-light);
}
.header__tagline {
margin-top: 14px;
font-size: 15px;
font-weight: 400;
color: var(--text-muted);
}
/* ── Bento Grid ── */
.bento-grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
grid-auto-rows: auto;
gap: 14px;
}
/* ── Card base ── */
.bento-card {
background: var(--bg-card);
border: 1px solid var(--border);
border-radius: var(--radius);
padding: 22px;
transition: background 0.25s ease, border-color 0.25s ease, transform 0.25s ease;
}
.bento-card:hover {
background: var(--bg-card-hover);
border-color: var(--border-hover);
transform: translateY(-2px);
}
/* ── Feature card (spans 2 cols) ── */
.bento-card--feature {
grid-column: span 2;
position: relative;
overflow: hidden;
padding: 28px;
}
.card-accent {
position: absolute;
top: -40px;
right: -40px;
width: 200px;
height: 200px;
background: radial-gradient(circle, rgba(99, 102, 241, 0.2), transparent 70%);
pointer-events: none;
}
.card-content {
position: relative;
z-index: 1;
}
.card-eyebrow {
font-size: 11px;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.1em;
color: var(--accent-light);
margin-bottom: 8px;
}
.card-title {
font-size: 22px;
font-weight: 700;
letter-spacing: -0.02em;
margin-bottom: 6px;
}
.card-desc {
font-size: 14px;
color: var(--text-muted);
line-height: 1.5;
margin-bottom: 16px;
}
/* ── Buttons ── */
.btn {
font-family: var(--font);
font-size: 13px;
font-weight: 600;
padding: 10px 20px;
border-radius: 10px;
border: none;
cursor: pointer;
transition: transform 0.15s ease, box-shadow 0.15s ease;
}
.btn--primary {
background: var(--accent);
color: white;
}
.btn--primary:hover {
transform: translateY(-1px);
box-shadow: 0 8px 24px rgba(99, 102, 241, 0.35);
}
/* ── Stat cards ── */
.bento-card--stat {
display: flex;
flex-direction: column;
gap: 4px;
}
.stat-value {
font-size: 28px;
font-weight: 800;
letter-spacing: -0.03em;
color: var(--text);
}
.stat-label {
font-size: 12px;
font-weight: 500;
color: var(--text-muted);
text-transform: uppercase;
letter-spacing: 0.06em;
}
.stat-bar {
height: 4px;
background: rgba(255, 255, 255, 0.06);
border-radius: 100px;
margin-top: 8px;
overflow: hidden;
}
.stat-bar-fill {
height: 100%;
background: var(--accent);
border-radius: 100px;
transition: width 1s ease;
}
.stat-bar-fill--green {
background: var(--green);
}
/* ── Profile card (spans 2 cols) ── */
.bento-card--profile {
grid-column: span 2;
display: flex;
flex-direction: column;
gap: 14px;
}
.profile-row {
display: flex;
align-items: center;
gap: 14px;
}
.avatar {
width: 44px;
height: 44px;
border-radius: 14px;
background: linear-gradient(135deg, var(--accent), var(--accent-light));
display: flex;
align-items: center;
justify-content: center;
font-size: 14px;
font-weight: 700;
color: white;
flex-shrink: 0;
}
.profile-info {
flex: 1;
}
.profile-name {
font-size: 15px;
font-weight: 600;
letter-spacing: -0.01em;
}
.profile-role {
font-size: 12px;
color: var(--text-muted);
margin-top: 2px;
}
.online-dot {
width: 8px;
height: 8px;
border-radius: 50%;
background: var(--green);
box-shadow: 0 0 6px var(--green);
flex-shrink: 0;
}
.profile-tags {
display: flex;
gap: 6px;
}
.tag {
font-size: 11px;
font-weight: 500;
padding: 4px 10px;
border-radius: 100px;
background: rgba(255, 255, 255, 0.05);
border: 1px solid var(--border);
color: var(--text-muted);
}
/* ── Wide card (spans 2 cols) ── */
.bento-card--wide {
grid-column: span 2;
}
.activity-row {
display: flex;
flex-direction: column;
gap: 10px;
}
.activity-item {
display: flex;
align-items: center;
gap: 10px;
font-size: 13px;
}
.activity-dot {
width: 6px;
height: 6px;
border-radius: 50%;
flex-shrink: 0;
}
.activity-dot--blue {
background: #60a5fa;
}
.activity-dot--green {
background: #34d399;
}
.activity-dot--purple {
background: #a78bfa;
}
.activity-label {
flex: 1;
color: var(--text);
font-weight: 500;
}
.activity-time {
font-size: 12px;
color: var(--text-dim);
flex-shrink: 0;
}
/* ── Input card ── */
.bento-card--input {
grid-column: span 2;
display: flex;
flex-direction: column;
gap: 8px;
}
.input-label {
font-size: 12px;
font-weight: 600;
color: var(--text-muted);
text-transform: uppercase;
letter-spacing: 0.08em;
}
.input-wrap {
display: flex;
align-items: center;
gap: 10px;
background: rgba(255, 255, 255, 0.04);
border: 1px solid var(--border);
border-radius: var(--radius-sm);
padding: 0 14px;
transition: border-color 0.2s ease, box-shadow 0.2s ease;
}
.input-wrap:focus-within {
border-color: rgba(99, 102, 241, 0.4);
box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.1);
}
.input-icon {
color: var(--text-dim);
flex-shrink: 0;
}
.bento-input {
flex: 1;
background: transparent;
border: none;
padding: 12px 0;
font-family: var(--font);
font-size: 14px;
color: var(--text);
outline: none;
}
.bento-input::placeholder {
color: var(--text-dim);
}
/* ── Responsive ── */
@media (max-width: 520px) {
.page {
padding: 32px 16px 48px;
gap: 24px;
}
.header__title {
font-size: clamp(32px, 10vw, 40px);
}
.bento-grid {
grid-template-columns: 1fr;
gap: 12px;
}
.bento-card--feature,
.bento-card--profile,
.bento-card--wide,
.bento-card--input {
grid-column: span 1;
}
.bento-card {
padding: 18px;
}
.bento-card--feature {
padding: 22px;
}
.stat-value {
font-size: 24px;
}
.card-title {
font-size: 18px;
}
}// Bento UI — subtle hover glow effect
document.querySelectorAll(".bento-card").forEach((card) => {
card.addEventListener("mousemove", (e) => {
const rect = card.getBoundingClientRect();
const x = e.clientX - rect.left;
const y = e.clientY - rect.top;
card.style.background = `radial-gradient(circle at ${x}px ${y}px, rgba(99, 102, 241, 0.06), rgba(255,255,255,0.04) 60%)`;
});
card.addEventListener("mouseleave", () => {
card.style.background = "";
});
});
// Animate stat bars on scroll into view
const observer = new IntersectionObserver(
(entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
const bar = entry.target.querySelector(".stat-bar-fill");
if (bar) {
const width = bar.style.width;
bar.style.width = "0%";
requestAnimationFrame(() => {
requestAnimationFrame(() => {
bar.style.width = width;
});
});
}
}
});
},
{ threshold: 0.5 }
);
document.querySelectorAll(".bento-card--stat").forEach((card) => observer.observe(card));<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap" rel="stylesheet" />
<link rel="stylesheet" href="style.css" />
<title>Bento UI — Design Style</title>
</head>
<body>
<div class="page">
<!-- Header -->
<header class="header">
<div class="header__pill">Modular Layout</div>
<h1 class="header__title">Bento<br /><span>Grid</span></h1>
<p class="header__tagline">Asymmetric grids. Clean modules. Visual harmony.</p>
</header>
<!-- Bento Grid -->
<section class="bento-grid">
<!-- Large feature card -->
<div class="bento-card bento-card--feature" id="card-feature">
<div class="card-accent"></div>
<div class="card-content">
<p class="card-eyebrow">Overview</p>
<h2 class="card-title">Design System</h2>
<p class="card-desc">Build consistent, beautiful interfaces with modular components.</p>
<button class="btn btn--primary">Get Started</button>
</div>
</div>
<!-- Stat card 1 -->
<div class="bento-card bento-card--stat" id="card-stat1">
<span class="stat-value">2.4K</span>
<span class="stat-label">Components</span>
<div class="stat-bar">
<div class="stat-bar-fill" style="width: 78%"></div>
</div>
</div>
<!-- Stat card 2 -->
<div class="bento-card bento-card--stat" id="card-stat2">
<span class="stat-value">99.8%</span>
<span class="stat-label">Uptime</span>
<div class="stat-bar">
<div class="stat-bar-fill stat-bar-fill--green" style="width: 99%"></div>
</div>
</div>
<!-- Profile card -->
<div class="bento-card bento-card--profile" id="card-profile">
<div class="profile-row">
<div class="avatar">MK</div>
<div class="profile-info">
<h3 class="profile-name">Maya Kim</h3>
<p class="profile-role">Product Designer</p>
</div>
<span class="online-dot"></span>
</div>
<div class="profile-tags">
<span class="tag">Figma</span>
<span class="tag">React</span>
<span class="tag">Motion</span>
</div>
</div>
<!-- Wide card -->
<div class="bento-card bento-card--wide" id="card-wide">
<div class="activity-row">
<div class="activity-item">
<div class="activity-dot activity-dot--blue"></div>
<span class="activity-label">UI Kit v3.2 shipped</span>
<span class="activity-time">2h ago</span>
</div>
<div class="activity-item">
<div class="activity-dot activity-dot--green"></div>
<span class="activity-label">Dashboard redesign approved</span>
<span class="activity-time">5h ago</span>
</div>
<div class="activity-item">
<div class="activity-dot activity-dot--purple"></div>
<span class="activity-label">New component library started</span>
<span class="activity-time">1d ago</span>
</div>
</div>
</div>
<!-- Input card -->
<div class="bento-card bento-card--input" id="card-input">
<label class="input-label" for="bentoSearch">Quick Search</label>
<div class="input-wrap">
<svg class="input-icon" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5">
<circle cx="11" cy="11" r="8"/><path d="m21 21-4.3-4.3"/>
</svg>
<input class="bento-input" id="bentoSearch" type="text" placeholder="Search components..." />
</div>
</div>
</section>
</div>
<script src="script.js"></script>
</body>
</html>Bento UI
Bento UI takes its name from the Japanese bento box — a compartmentalized container where each section has a clear purpose and proportion. In web design, this translates to asymmetric grid layouts where cards of varying sizes sit together in a harmonious, visually balanced arrangement.
The hallmark of Bento UI is the use of CSS Grid with grid-template-columns and grid-template-rows to create cards that span different numbers of columns and rows. Large feature cards sit beside smaller stat tiles and medium info panels, creating visual hierarchy without relying on typography alone. Generous border-radius (typically 20–28px) and subtle shadows give each tile a soft, tactile quality.
Color palettes are restrained — usually a dark or near-black background with cards in slightly elevated tones (rgba(255,255,255,0.05) to 0.08), accented with a single vibrant color for CTAs and highlights. This approach lets the layout itself be the star.
Key characteristics
- Asymmetric CSS Grid with cards spanning 1–3 columns and 1–2 rows
- Large border-radius (20–28px) for soft, rounded containers
- Dark background with subtle card elevation differences
- Accent color used sparingly for highlights and interactive elements
- Clean typography with strong hierarchy (size contrast)
- Hover effects that subtly lift or highlight individual tiles
When to use it
Bento UI is perfect for dashboards, feature showcases, product landing pages, portfolio overviews, and settings panels. It works best when you have multiple distinct pieces of content to display simultaneously with clear visual hierarchy.