Hybrid Astro UI

A responsive grid layout system for creating bento-style layouts with zero runtime JavaScript. Features flexible column and row spanning, responsive breakpoints, and customizable gaps. Perfect for building modern, dashboard-style interfaces.

Hybrid Astro UI

Build modern, bento-style layouts with zero runtime JS. Fully static. Fully editable. Fully yours.

Zero JS

No hydration, no runtime cost.

Astro-native

Designed for content-first sites.

Dashboard preview

100%

Editable code

0 KB

Client JS

Composable

Build layouts like LEGO blocks.

  • • Grid-based
  • • Responsive
  • • Accessible

Ready to ship faster?

View on GitHub

Install

pnpm dlx hybrid-astro-ui@latest add bento-grid
npx hybrid-astro-ui@latest add bento-grid
yarn dlx hybrid-astro-ui@latest add bento-grid
bunx hybrid-astro-ui@latest add bento-grid

Usage

The Bento Grid system consists of two main components: BentoGrid (the container) and BentoItem (the grid items). They work together to create responsive, bento-style layouts.

BentoGrid creates the grid container with configurable columns and gaps:

---
import { BentoGrid, BentoItem } from "@/src/components/hybrid-astro-ui/bento-grid"
---

<BentoGrid cols={3} mdCols={4} lgCols={6} gap="gap-6">
  <!-- BentoItem components go here -->
</BentoGrid>

represents individual grid items with flexible spanning:

<BentoGrid cols={3} gap="gap-4">
  <!-- Default item (spans 1 column, 1 row) -->
  <BentoItem>
    <div>Content here</div>
  </BentoItem>
  
  <!-- Item that spans 2 columns -->
  <BentoItem span={2}>
    <div>Wide content</div>
  </BentoItem>
  
  <!-- Item that spans 2 rows -->
  <BentoItem row={2}>
    <div>Tall content</div>
  </BentoItem>
  
  <!-- Item that spans 2 columns and 2 rows -->
  <BentoItem span={2} row={2}>
    <div>Large content area</div>
  </BentoItem>
</BentoGrid>

Responsive Design

Both components support responsive breakpoints with , , and prefixes:

<BentoGrid cols={2} mdCols={3} lgCols={4} gap="gap-4">
  <!-- Responsive item: 1 column on mobile, 2 on tablet, 3 on desktop -->
  <BentoItem span={1} md={2} lg={3}>
    <div>Adaptive content</div>
  </BentoItem>
  
  <!-- Responsive rows: 1 row tall on mobile, 2 on larger screens -->
  <BentoItem row={1} mdRow={2}>
    <div>Adaptive height content</div>
  </BentoItem>
</BentoGrid>

Complete Example

---
import { BentoGrid, BentoItem } from "@/src/components/hybrid-astro-ui/bento-grid"
---

<BentoGrid cols={2} mdCols={4} lgCols={6} gap="gap-6">
  <!-- Hero section - spans full width on mobile, large on desktop -->
  <BentoItem span={2} row={2} md={3} mdRow={2} lg={4} lgRow={2}>
    <div class="h-full flex flex-col justify-between">
      <div>
        <h1 class="text-3xl font-semibold mb-3">Your Title</h1>
        <p class="text-muted-foreground max-w-md">
          Your description text goes here.
        </p>
      </div>
      <div class="mt-6 flex gap-3">
        <button class="px-4 py-2 rounded-md bg-primary text-primary-foreground">
          Get started
        </button>
        <button class="px-4 py-2 rounded-md border">
          Learn more
        </button>
      </div>
    </div>
  </BentoItem>

  <!-- Feature cards -->
  <BentoItem>
    <h3 class="font-medium mb-1">Feature One</h3>
    <p class="text-sm text-muted-foreground">Description of feature one.</p>
  </BentoItem>

  <BentoItem>
    <h3 class="font-medium mb-1">Feature Two</h3>
    <p class="text-sm text-muted-foreground">Description of feature two.</p>
  </BentoItem>

  <!-- Image or media item -->
  <BentoItem span={2} md={4} lg={2}>
    <div class="relative h-full rounded-lg overflow-hidden flex items-center justify-center">
      <img src="/your-image.jpg" alt="Preview" class="object-cover" />
    </div>
  </BentoItem>

  <!-- Stats items -->
  <BentoItem>
    <p class="text-3xl font-bold">100%</p>
    <p class="text-xs text-muted-foreground">Performance</p>
  </BentoItem>

  <BentoItem>
    <p class="text-3xl font-bold">0 KB</p>
    <p class="text-xs text-muted-foreground">JavaScript</p>
  </BentoItem>

  <!-- Call to action -->
  <BentoItem row={2} lgRow={2} span={2}>
    <div class="h-full flex flex-col justify-between">
      <div>
        <h3 class="font-medium mb-2">Ready to start?</h3>
        <p class="text-sm text-muted-foreground">
          Build amazing layouts with zero runtime JavaScript.
        </p>
      </div>
      <ul class="text-sm space-y-1">
        <li>• Grid-based layouts</li>
        <li>• Fully responsive</li>
        <li>• Accessible by default</li>
      </ul>
    </div>
  </BentoItem>
</BentoGrid>

API Reference

BentoGrid Props
PropTypeDefaultDescription
cols1 - 2 - 3 - 4 - 5 - 63Number of columns on mobile
smCols1 - 2 - 3 - 4 - 5 - 6-Number of columns on small screens (640px+)
mdCols1 - 2 - 3 - 4 - 5 - 6-Number of columns on medium screens (768px+)
lgCols1 - 2 - 3 - 4 - 5 - 6-Number of columns on large screens (1024px+)
gap'gap-2' - 'gap-4' - 'gap-6''gap-4'Spacing between grid items
classstring-Additional CSS classes
BentoItem Props
PropTypeDefaultDescription
span1 - 2 - 3 - 4 - 5 - 61Number of columns to span on mobile
row1 - 2 - 3 - 4 - 5 - 61Number of rows to span on mobile
sm1 - 2 - 3 - 4 - 5 - 6-Column span on small screens
md1 - 2 - 3 - 4 - 5 - 6-Column span on medium screens
lg1 - 2 - 3 - 4 - 5 - 6-Column span on large screens
smRow1 - 2 - 3 - 4 - 5 - 6-Row span on small screens
mdRow1 - 2 - 3 - 4 - 5 - 6-Row span on medium screens
lgRow1 - 2 - 3 - 4 - 5 - 6-Row span on large screens
classstring-Additional CSS classes

Tips & Best Practices