Tempa UI

Bento Grid

Asymmetric grid layout for showcasing content in varied tile sizes.

Code

components/BentoGrid.astro
    
      ---import type { ImageMetadata } from "astro"; interface BentoItem {  title: string;  description?: string;  size?: "sm" | "md" | "lg" | "featured";  imageSrc?: ImageMetadata | string;  imageOverlay?: boolean;  class?: string;} interface Props {  items: BentoItem[];  class?: string;} const {  items,  class: className = "",} = Astro.props; const sizeClasses = {  sm: "md:col-span-1 md:row-span-1",  md: "md:col-span-1 md:row-span-2",  lg: "md:col-span-2 md:row-span-1",  featured: "md:col-span-2 md:row-span-2",};--- <div class:list={["grid grid-cols-1 md:grid-cols-4 gap-3 md:gap-4 auto-rows-auto md:auto-rows-fr", className]}>  {items.map((item) => {    const bgUrl = item.imageSrc      ? typeof item.imageSrc === "string"        ? item.imageSrc        : item.imageSrc.src      : null;     const showOverlay = item.imageSrc && item.imageOverlay !== false;     return (      <div        class:list={[          "rounded-xl p-5 md:p-6 flex flex-col justify-center bg-cover bg-center relative",          sizeClasses[item.size || "sm"],          item.imageSrc ? "text-white-ghost" : item.class || "bg-black-onyx/5 text-black-onyx",        ]}        style={bgUrl ? { backgroundImage: `url(${bgUrl})` } : undefined}      >        {showOverlay && (          <div class="absolute inset-0 bg-black-onyx/50 rounded-xl" />        )}        <div class="relative z-10">          <h3 class="text-sm md:text-base font-semibold">{item.title}</h3>          {item.description && (            <p class="text-xs md:text-sm mt-1 leading-relaxed opacity-80">              {item.description}            </p>          )}        </div>      </div>    );  })}</div> 
    
  

Preview

Default Bento Grid

Lightweight

Only 15KB minified. No bloat, no unnecessary dependencies.

Copy-Paste

No npm install. Copy the code and paste it directly.

Customizable

CSS variables for every component.

Responsive

Mobile-first design. Works on every screen size.

With Background Image

Desktop Setup

Clean workspace for focused development.

Minimal

Less is more.

Clean

Organized and tidy.

Modern

Contemporary design.

Productive

Built for efficiency.

Usage

    
      <BentoGrid  items={[    { title: "Feature A", description: "Description", size: "featured" },    { title: "Feature B", description: "Description", size: "lg" },    { title: "Feature C", description: "Description", size: "sm" },    { title: "Feature D", description: "Description", size: "sm" },    { title: "Feature E", description: "Description", size: "md" },  ]}/>
    
  
    
      <BentoGrid  items={[    { title: "With Image", description: "This card uses a background image", size: "featured", imageSrc: Desktop },    { title: "Normal", description: "Regular card", size: "sm" },    { title: "Normal", description: "Regular card", size: "sm" },    { title: "Normal", description: "Regular card", size: "sm" },    { title: "Normal", description: "Regular card", size: "md" },  ]}/>
    
  

Props

Prop Type Default Description
items BentoItem[] Array of grid items with title, description, size, imageSrc, and optional class.
class string Additional CSS classes.

Item Fields

Field Type Default Description
title string Card title.
description string Optional description text.
size "sm" | "md" | "lg" | "featured" "sm" Grid span size.
imageSrc ImageMetadata | string Background image (imported or URL).
imageOverlay boolean true Dark overlay for text readability.
class string Custom background/text color (ignored when imageSrc is set).

Item Sizes

Size Mobile Desktop
sm 1 col 1 col × 1 row
md 1 col 1 col × 2 rows
lg 1 col 2 cols × 1 row
featured 1 col 2 cols × 2 rows