Offset Image Pair Hero

(Studio, since 2014)

Two pictures usually settle it faster than two decks.

We work in images from the first week: rough, printed, pinned to a wall you can stand in front of and argue with.

Type specimen sheets laid out on a studio table
Specimen table, week two
Two studio members reviewing prints on a wall
Wall review, week five
About this block

Offset Image Pair HeroPRO

Split hero pairing a statement, paragraph and two pill CTAs with a pair of captioned portrait images, the second dropped by a stagger on desktop so the column reads as an editorial spread.

Hero150: Offset Image Pair Hero

A two-column hero where the copy sits beside a pair of captioned portraits, the second dropped down the page so the pictures read as prints pinned at different heights rather than a tidy pair of cards.

Upgrade to Pro

Pro blocks install through the shadcn CLI with your license key and ship their full source. Docs and live previews stay open to everyone, so you can read every block's details first.

Upgrade Now

Installation

Swap YOUR_EMAIL and YOUR_KEY for the email and license key on your account. Find your license key on your account page.

Radix flavor

bash
npx shadcn add "https://ui.beste.co/r/hero150?email=YOUR_EMAIL&license_key=YOUR_KEY"

Base UI flavor

bash
npx shadcn add "https://ui.beste.co/r-base/hero150?email=YOUR_EMAIL&license_key=YOUR_KEY"

This installs the block to components/beste/block/hero150.tsx plus the badge7 eyebrow and button12 pill button it uses.

Quick start

The installed file exports hero150Demo alongside the block: the exact props behind the preview above. Spread it to get a working hero in one line.

tsx
import { Hero150, hero150Demo } from "@/components/beste/block/hero150";

export default function Page() {
  return <Hero150 {...hero150Demo} />;
}

Then replace the demo with your own props. Written out, a trimmed setup looks like this:

tsx
import { Hero150 } from "@/components/beste/block/hero150";

export default function Page() {
  return (
    <Hero150
      badge={{ label: "Studio, since 2014" }}
      heading="Two pictures usually settle it faster than two decks."
      description="We work in images from the first week: rough, printed, pinned to a wall."
      buttons={[
        { label: "Look at the work", href: "/work", tone: "dark" },
        { label: "Book a studio visit", href: "/contact", tone: "outline" },
      ]}
      images={[
        { src: "/studio/specimens.jpg", alt: "Specimen sheets on a table", caption: "Specimen table, week two" },
        { src: "/studio/wall.jpg", alt: "Reviewing prints on a wall", caption: "Wall review, week five" },
      ]}
    />
  );
}

Props

PropTypeDefaultDescription
badge{ label: string }Eyebrow label rendered as a Badge7
headingstringDisplay statement, rendered as the page h1
descriptionstringSupporting paragraph under the statement
buttonsActionButton[][]CTAs rendered as Button12, each with its own tone
imagesCaptionedImage[][]Portraits in the right column, every second one offset
classNamestringExtra classes for the outer <section>
ts
type CaptionedImage = {
  src: string;
  alt: string;
  caption: string;
};

type ActionButton = {
  label: string;
  href: string;
  tone?: "dark" | "outline";
};

Behavior notes

  • The offset is applied with md:mt-16 on every odd image, so it only appears from md up; on a phone the two portraits stay level and the column reads as a plain pair.
  • tone defaults to "dark", so a button list with no tone set still renders a solid primary pill first.
  • Images render as real figure and figcaption elements, with the caption under the frame as plain muted text rather than on a scrim.
  • The portrait ratio is fixed at aspect-[3/4] for every image, so a landscape source is cropped into the pair rather than breaking the offset rhythm.
  • The two columns are md:items-center, which keeps the copy optically level with a picture column that is taller on one side than the other.
  • The heading is capped at max-w-xl while the section runs to max-w-7xl, so the statement holds a readable measure instead of stretching across the column.
  • Buttons wrap with flex-wrap gap-3, so a third CTA drops to a second line at its natural width rather than compressing the row.

More Hero blocks

View all Hero
PRO

hero112

Editorial Split Hero

Two-column studio hero with a two-tone headline, dual CTAs, tall image and a client wordmark strip.

PRO

hero121

Split Hero with Stats

Split hero with a big headline and CTA on the left, a divided vertical stat rail on the right, and a full-width wide image strip below.

PRO

hero114

Collage Hero

Split studio hero with a two-tone headline and a four-image arranged collage.

PRO

hero156

Split Screen Panel Hero

Edge-to-edge split hero: a dark half carries the statement, paragraph, outline pill CTA and a ruled detail row, while the other half is a full-height photograph with a pill caption in its corner.

PRO

hero143

Editorial Split Hero

A light editorial hero with an oversized display heading on the left, an offset supporting paragraph and accent button on the right, and a full-bleed image band below.

PRO

hero166

Split Headline Hero

An editorial hero that breaks its display heading across two lines and slots a square image tile floating a live payment card into the gap, with the paragraph and action landing under a hairline.