Nature
#1Sunset Boulevard
Golden hour across the bay
Item width: 100%
Loading...
Please waitLayout helper that returns responsive column counts and item sizing for adaptive masonry or grid layouts.
pnpm dlx uselab@latest add use-responsive-grid
import * as React from "react"
import { useResponsiveGrid } from "@/hooks/use-responsive-grid"
const breakpoints = [
{ minWidth: 0, columns: 1 },
{ minWidth: 640, columns: 2 },
{ minWidth: 900, columns: 3 },
{ minWidth: 1200, columns: 4 },
]
export function Gallery() {
const { columns, itemStyle, containerStyle } = useResponsiveGrid({
breakpoints,
gap: 24,
layout: "masonry",
})
return (
<div style={containerStyle}>
{Array.from({ length: 8 }).map((_, index) => (
<div key={index} style={itemStyle} className="rounded-md bg-muted p-4">
Item {index + 1}
</div>
))}
</div>
)
}| Name | Type | Description | Default Value | Optional |
|---|---|---|---|---|
breakpoints | ResponsiveBreakpoint[] | Array of { minWidth, columns } rules, evaluated from smallest to largest screen width. | — | No |
gap | number | Gap between grid items (in pixels). | 16 | Yes |
defaultColumns | number | Fallback column count for SSR or widths below the first breakpoint. | 1 | Yes |
layout | "flex" | "masonry" | Choose between a flex-based grid or CSS column masonry layout. | "flex" | Yes |
| Name | Type | Description |
|---|---|---|
columns | number | Current number of columns that match the viewport width. |
gap | number | Gap passed to the hook. |
layout | "flex" | "masonry" | Currently applied layout mode. |
containerStyle | React.CSSProperties | Styles to spread on the outer wrapper (flex or column masonry). |
itemStyle | React.CSSProperties | Styles for each item (width/flex for grid, break-inside for masonry). |
{ minWidth: 0, columns: 1 }) to guarantee a valid layout.display: flex and flex-wrap: wrap to honor item widths.columns to derive grid-template-columns: repeat(columns, minmax(0, 1fr)).const { columns, itemStyle, gap } = useResponsiveGrid({
breakpoints: [
{ minWidth: 0, columns: 1 },
{ minWidth: 768, columns: 2 },
{ minWidth: 1024, columns: 3 },
],
gap: 18,
})
return (
<div style={containerStyle}>
{photos.map((photo) => (
<figure key={photo.id} style={itemStyle}>
<img src={photo.src} alt={photo.alt} className="w-full rounded-lg" />
</figure>
))}
</div>
)const { columns, containerStyle, itemStyle } = useResponsiveGrid({
breakpoints: [
{ minWidth: 0, columns: 1 },
{ minWidth: 600, columns: 2 },
{ minWidth: 900, columns: 3 },
],
})
return (
<div
style={{
...containerStyle,
display: "grid",
gap: 16,
gridTemplateColumns: `repeat(${columns}, minmax(0, 1fr))`,
}}
>
{widgets.map((widget) => (
<Widget key={widget.id} data={widget} style={itemStyle} />
))}
</div>
)const gap = useIsCompactMode() ? 12 : 24
const { containerStyle, itemStyle } = useResponsiveGrid({ breakpoints, gap })
return (
<div style={containerStyle}>
{items.map((item) => (
<Card key={item.id} style={itemStyle} />
))}
</div>
)useMemo if needed).defaultColumns until the client width is known.itemStyle uses calc() to subtract gaps, ensuring items fill the row without overflow.columns with CSS Grid templates for traditional grids, or use itemStyle with flexbox for masonry-style layouts.Masonry uses CSS columns (`break-inside: avoid`) to achieve true staggered heights.
Active breakpoints
Golden hour across the bay
Switchbacks leading to the summit
Neon reflections after rain
Pour-over morning routine
Minimal dunes at dusk
Patterns in modern architecture