A forest-green story band with text and a button beside four photos in two staggered columns. React and Tailwind CSS, no dependencies.
StoryWithStaggeredGallery.tsx
// Forest-green story band: heading, paragraphs and button on the left, four
// photos in two staggered columns on the right.
// Pure Tailwind, no dependencies. Works with Tailwind v3 and v4.
type Props = {
eyebrow?: string;
heading?: string;
paragraphs?: string[];
cta?: { label: string; href: string };
photos?: { src: string; alt: string }[];
};
const img = (id: string) => `https://images.unsplash.com/photo-${id}?w=900&q=80&auto=format&fit=crop`;
const DEFAULT_PHOTOS = [
{ src: img("1541972184324-d7e22e823db4"), alt: "A toast at sunset" },
{ src: img("1600812703042-38e573598898"), alt: "Long table set for dinner" },
{ src: img("1492684223066-81342ee5ff30"), alt: "Confetti over a dance floor" },
{ src: img("1784558525815-87e21a67b3f3"), alt: "Champagne by an infinity pool" },
];
export default function StoryStaggeredGallery({
eyebrow = "Our story",
heading = "Weddings that feel like you",
paragraphs = [
"We started planning weddings for friends twelve years ago, and never stopped. Today we're a small team of planners, stylists and coordinators.",
"We take on a limited number of weddings each year, so every couple gets our full attention from the first coffee to the last dance.",
],
cta = { label: "Meet the team", href: "#" },
photos = DEFAULT_PHOTOS,
}: Props) {
const columns = [photos.filter((_, i) => i % 2 === 0), photos.filter((_, i) => i % 2 === 1)];
return (
<section className="bg-[#2F3D2C] px-5 py-24 font-['Manrope',ui-sans-serif,system-ui,sans-serif] text-[#F5F4EC] antialiased md:px-10 md:py-40">
<div className="mx-auto grid max-w-7xl items-center gap-16 md:grid-cols-12 md:gap-8">
<div className="md:col-span-6 lg:col-span-5">
<p className="mb-6 text-xs font-semibold uppercase tracking-[0.2em] text-[#F5D86A]">{eyebrow}</p>
<h2 className="font-['Instrument_Serif',Georgia,serif] text-[clamp(2.75rem,5vw,4.5rem)] leading-none">{heading}</h2>
<div className="mt-8 space-y-5 border-t border-current/15 pt-8">
{paragraphs.map((p) => (
<p key={p} className="leading-relaxed opacity-80">
{p}
</p>
))}
</div>
{cta && (
<a href={cta.href} className="mt-10 inline-flex items-center gap-6 bg-[#F5D86A] px-6 py-4 text-sm font-semibold text-[#2F3D2C] transition-colors hover:bg-white md:mt-12">
{cta.label} <span aria-hidden>→</span>
</a>
)}
</div>
<div className="grid grid-cols-2 gap-4 md:col-span-6 md:col-start-7 md:gap-6">
{columns.map((column, c) => (
<div key={c} className={`flex flex-col gap-4 md:gap-6 ${c === 1 ? "mt-16 md:mt-24" : ""}`}>
{column.map((photo) => (
<div key={photo.src} className="aspect-[3/4] overflow-hidden bg-white/10">
<img src={photo.src} alt={photo.alt} loading="lazy" className="h-full w-full object-cover" />
</div>
))}
</div>
))}
</div>
</div>
</section>
);
}
How to use it
- Make sure your Next.js or React project has Tailwind CSS set up (v3 or v4 both work).
- Create
components/StoryWithStaggeredGallery.tsxand paste the code. - Import it into a page and replace the sample text and images with your own.
