Overview
Hero is a CORE-OWNED pure-content section component in src/core/components/sections/Hero.astro. It renders hero content — heading, subheading, action buttons, and optional image — but does not own surface concerns (background, vertical padding) or container concerns (content width, gutter). Callers compose Hero inside LayoutSection to provide those concerns.
All page, article-detail, and docs-detail routes render their heading band through Hero in the PageGridLayout subheader slot, wrapped in a LayoutSection.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
heading | string | required | Hero heading text |
subheading | string | — | Supporting text rendered below the heading (max-width 60ch) |
headingLevel | 1–6 | 1 | Semantic heading level |
headingSize | xs–display | automatic (from Heading component) | Visual heading size (decoupled from semantic level) |
primaryAction | SectionAction | — | Primary CTA button |
secondaryAction | SectionAction | — | Secondary CTA button. Only rendered when primaryAction is also present. |
image | SectionMedia | — | Hero image with src and alt |
imagePosition | "left" | "right" | "right" | Which side of the content the image appears on in split layout |
splitAt | "md" | "lg" | "lg" | Breakpoint at which the content/image stack switches to a side-by-side grid |
align | SectionAlign | "left" | Text and content alignment |
class | string | — | Additional CSS classes |
All other HTML attributes (id, aria-*, data-*, etc.) are forwarded to the root <div> via attribute passthrough.
Behavior
Image split layout
When image is provided, the hero renders a two-column grid. The splitAt prop controls the responsive breakpoint:
- Below the breakpoint: content and image stack vertically (single column).
- At or above the breakpoint: content and image display side-by-side with the image column at approximately 90% of the content column width.
The imagePosition prop controls column order — "left" uses CSS grid reordering to place the image before the content.
Actions
secondaryAction is only rendered when primaryAction is also present. Each action renders as a Button component. The action’s variant defaults to "primary" for the primary action and "secondary" for the secondary action, but can be overridden via the SectionAction.variant field.
Alignment
The align prop controls text alignment and flex alignment of the content column:
"left"(default) — left-aligned text and items"center"— centered text and items"right"— right-aligned text and items
CSS API
BEM root class: hero
| Class | Element | Rendering path |
|---|---|---|
.hero | Component root (<div>) | Always |
.hero__inner | Grid container for content/image | Complex only |
.hero__content | Content column (heading + actions) | Complex only |
.hero__heading | Heading element | Always |
.hero__subheading | Subheading paragraph | Always |
.hero__actions | Actions container (button row) | Complex only |
.hero__media | Image wrapper | Complex only |
.hero__media-img | Image element | Complex only |
Rendering paths: Hero has two rendering paths based on prop usage. The complex path renders when image or primaryAction is provided — it includes the full __inner grid wrapper and __content flex wrapper for image-split and action layouts. The text-only path renders when neither image nor primaryAction is provided — heading and subheading render directly inside the .hero root with no intermediate wrappers, reducing DOM depth by 2 levels. Classes marked “Complex only” above are not present in the text-only path DOM.
Modifier classes applied automatically:
| Modifier | Applied when | Rendering path |
|---|---|---|
.hero--align-center | align="center" | Always |
.hero--align-right | align="right" | Always |
.hero__inner--with-image | image is provided | Complex only |
.hero__inner--image-left | imagePosition="left" | Complex only |
.hero__inner--image-right | imagePosition="right" | Complex only |
.hero__inner--split-md | splitAt="md" | Complex only |
.hero__inner--split-lg | splitAt="lg" | Complex only |
These classes are available as CSS API hooks for site-level overrides in src/site/styles/.
Migration note (0.x contract change): Prior to this change,
.hero__innerand.hero__contentwere always rendered, even for text-only heroes. Site-level overrides targeting these classes for compact page-title-band heroes will no longer match. Retarget those overrides to.heroinstead. The complex path (image or action heroes) is unchanged.
Usage
Hero is wrapped in a LayoutSection to provide surface and container framing. In standard routes, it is placed in the PageGridLayout subheader slot:
<LayoutSection slot="subheader" contentWidth="wide" verticalPadding="lg">
<Hero heading="Page Title" />
</LayoutSection>
For a full marketing hero with image and actions:
<LayoutSection slot="subheader" background="primary" verticalPadding="2xl">
<Hero
heading="Build something great"
subheading="A modern platform for your next project."
primaryAction={{ label: "Get Started", href: "/get-started" }}
secondaryAction={{ label: "Learn More", href: "/docs" }}
image={{ src: "/images/hero.jpg", alt: "Product screenshot" }}
/>
</LayoutSection>
Note: To customize hero appearance at the site level, target the BEM classes above in site-owned stylesheets rather than modifying the core component.