Skip to content

Hero

A prominent section typically at the top of a page with a headline, description, and CTA.

  • Hero Section
  • Banner
  • Jumbotron

Overview

The Hero section (also known as a hero banner, jumbotron, or above-the-fold banner) is a prominent visual component typically placed at the top of a page to immediately communicate the page's primary message, value proposition, or call-to-action. It is the first thing a user sees and sets the visual tone for the entire experience.

Hero sections combine typography, imagery (or color/gradient backgrounds), and calls-to-action into a single high-impact composition. They are used across marketing pages, landing pages, product pages, blog headers, and application dashboards.

When to use a Hero:

  • At the top of landing pages to communicate the core value proposition
  • On product pages to showcase the primary product with imagery and a CTA
  • On blog posts or articles as a visual header with the title and metadata
  • On dashboards or app pages as a welcome/overview banner
  • On error pages (404, 500) to provide a branded, friendly experience

When NOT to use a Hero:

  • On data-dense pages where users need immediate access to content (dashboards with many widgets)
  • When the page serves a utility purpose where a hero adds unnecessary scrolling
  • Below the fold — heroes are designed for the top of the page
  • When you don't have strong visual content or a clear message — a weak hero damages credibility

Use the Gradient Generator to create background gradients for your hero. Set type scales with the Font Scale Generator. Verify text-over-image contrast with the Contrast Checker.

Variants

Layout Variants

VariantDescriptionBest For
CenteredAll content centered horizontally and vertically. Single column.Simple landing pages, announcement pages, brand pages
SplitContent on one side, image/media on the other (50/50 or 60/40).Product pages, SaaS landing pages, feature showcases
Full-imageFull-bleed background image with overlaid text.Visual-heavy brands, photography, travel, lifestyle
Video backgroundLooping video behind text content.Modern SaaS, creative agencies, event pages
GradientGradient background (solid or mesh) with text overlay.Tech products, apps, where photography isn't available
MinimalText-only, no background image, relying on typography and whitespace.Content-focused sites, blogs, documentation
IllustratedCustom illustration (SVG/animation) alongside or behind text.Playful brands, fintech, developer tools
Card heroContent contained within a card element on a subtle background.Dashboard welcomes, nested hero sections

Size Variants

SizeHeightViewport CoverageUse Case
Full viewport100vhEntire screenBrand-focused landing pages, single-page sites
Large70–80vhMajority of viewportProduct pages, marketing pages
Medium50vh or 400–500pxHalf viewportBlog headers, secondary pages
Small200–300pxCompactSection headers, dashboard banners

Background Treatment

TreatmentDescriptionTool
Solid colorSingle brand colorContrast Checker
Linear gradientTwo or more colors in a directional gradientGradient Generator
Radial/mesh gradientComplex multi-point gradients for depthGradient Generator
Image with overlayPhoto with semi-transparent color overlay for text readabilityContrast Checker
Image with scrimGradient overlay (transparent to dark) from text area toward imageContrast Checker
Pattern/textureSVG pattern or subtle texture behind content—

Properties

Hero Properties

PropertyTypeDefaultDescription
variant'centered' | 'split' | 'fullImage' | 'minimal' | 'gradient''centered'Layout variant
size'sm' | 'md' | 'lg' | 'full''lg'Height preset
heightstring—Custom height (overrides size)
minHeightstring—Minimum height
backgroundImagestring—URL for background image
backgroundColorstring—Background color or CSS gradient
overlaybooleantrueApplies a semi-transparent overlay for text readability
overlayColorstring'rgba(0,0,0,0.4)'Overlay color and opacity
overlayGradientstring—CSS gradient used as overlay (e.g., scrim)
titleReactNode—Primary heading content
subtitleReactNode—Secondary text or description
actionsReactNode—CTA buttons or action elements
mediaReactNode—Image, video, or illustration for split layout
mediaPosition'left' | 'right''right'Side of the media in split variant
textAlign'left' | 'center' | 'right''center'Text alignment within the content area
maxWidthstring'720px'Maximum width of the text content area
verticalAlign'top' | 'center' | 'bottom''center'Vertical alignment of content within the hero
breadcrumbReactNode—Breadcrumb navigation displayed above the title
badgeReactNode—Badge or label above the title (e.g., "New", "Beta")
classNamestring—Custom CSS class

CSS Custom Properties

Custom PropertyDescriptionDefault
--hero-heightSection height80vh
--hero-min-heightMinimum height400px
--hero-bgBackground color/gradienttransparent
--hero-overlayOverlay colorrgba(0,0,0,0.4)
--hero-content-max-widthContent max-width720px
--hero-padding-xHorizontal padding24px
--hero-padding-yVertical padding48px
--hero-title-sizeTitle font sizeclamp(2rem, 5vw, 4rem)
--hero-subtitle-sizeSubtitle font sizeclamp(1rem, 2vw, 1.5rem)

Token Mappings

Design Token Mappings

TokenRoleTypical Value
color.bg.brandBrand-colored hero backgroundBrand primary
color.bg.surfaceMinimal hero background#ffffff / #1a1a1a
color.text.on-brandText color on brand background#ffffff
color.text.on-darkText on dark overlays#ffffff
color.text.primaryText on light/minimal heroes#111827
color.text.secondarySubtitle text on light heroes#6b7280
font.size.display-lgHero title (large variant)clamp(2.5rem, 5vw, 4.5rem)
font.size.display-mdHero title (medium variant)clamp(2rem, 4vw, 3rem)
font.size.xlHero subtitleclamp(1.125rem, 2vw, 1.5rem)
font.weight.boldTitle font weight700
font.weight.normalSubtitle font weight400
line-height.tightTitle line height1.1–1.2
line-height.relaxedSubtitle line height1.5–1.6
space.6Gap between title and subtitle24px
space.8Gap between subtitle and CTA32px
space.12 – space.16Hero vertical padding48–64px
radius.lg – radius.xlCard hero border radius16–24px

Configure your typography scale with the Font Scale Generator. Preview gradient backgrounds in the Gradient Generator. Verify text contrast with the Contrast Checker.

States

Hero States

Hero is primarily a static presentational component, but it has important viewport-driven and content-driven states:

StateTriggerEffect
DefaultPage loadFull hero renders with background, text, and CTAs
Responsive mobileViewport < 768pxSplit heroes stack vertically, font sizes reduce via clamp(), padding decreases
Background loadingLarge background image loadingShow a solid-color fallback or gradient while the image loads
Background loadedImage fully loadedCross-fade or instant swap to the background image
Video playingAutoplay video backgroundVideo loops silently; falls back to poster image if autoplay is blocked
Reduced motionprefers-reduced-motion: reduceVideo backgrounds pause (show poster), animations are disabled, parallax is removed
High contrastprefers-contrast: moreOverlay opacity increases, text borders/shadows added for clarity
PrintPrint mediaBackground images hidden, text displayed in print-friendly colors

Responsive Typography

Hero typography should use fluid sizing with clamp() to scale smoothly between viewport sizes:

.hero__title {
  font-size: clamp(2rem, 5vw, 4rem);
  line-height: 1.1;
}
.hero__subtitle {
  font-size: clamp(1rem, 2vw, 1.5rem);
  line-height: 1.5;
}

This eliminates the need for breakpoint-specific font-size media queries. Configure your fluid type scale with the Font Scale Generator.

Background Image Loading

Always provide a background-color fallback that closely matches the dominant color of the hero image. This prevents a jarring white-to-image flash:

.hero {
  background-color: #1a1a2e; /* dominant image color */
  background-image: url('hero.webp');
  background-size: cover;
  background-position: center;
}

Accessibility

Accessibility Requirements

Hero sections present significant accessibility challenges due to their reliance on visual impact, background imagery, and often low contrast ratios between text and backgrounds.

WCAG Success Criteria:

  • 1.4.3 Contrast (Minimum) (Level AA): All text in the hero must achieve at least 4.5:1 contrast for normal text and 3:1 for large text (≥ 18pt or 14pt bold) against its background. For text over images, this means testing against the worst-case area of the image where text appears — not just the average color. Use a semi-transparent overlay or scrim gradient to guarantee contrast. Verify with the Contrast Checker.
  • 1.4.6 Contrast (Enhanced) (Level AAA): For enhanced accessibility, aim for 7:1 (normal text) and 4.5:1 (large text). Hero titles (typically ≥ 24px bold) qualify as large text and need 3:1 minimum, 4.5:1 enhanced.
  • 1.4.11 Non-text Contrast (Level AA): CTA buttons and interactive elements within the hero must maintain 3:1 contrast against their background.
  • 1.1.1 Non-text Content (Level A): Background images that convey information (not purely decorative) must have text alternatives. If the background image is decorative (which is typical for heroes), it should be applied via CSS background-image (which is inherently hidden from AT) rather than <img>.
  • 1.4.10 Reflow (Level AA): Hero content must reflow to a single column at 320px width without horizontal scrolling. Split heroes must stack. Full-viewport heroes should transition to auto-height on mobile.
  • 2.3.1 Three Flashes or Below Threshold (Level A): Video backgrounds must not contain sequences that flash more than three times per second. This can trigger seizures. Review video content or use a static poster image fallback.
  • 1.4.12 Text Spacing (Level AA): Hero text must remain readable when users apply custom text spacing (line-height 1.5×, letter-spacing 0.12em, word-spacing 0.16em, paragraph spacing 2×). Avoid fixed-height containers that clip text when spacing increases.
  • 2.2.2 Pause, Stop, Hide (Level A): If the hero has an auto-playing video or animated content, provide controls to pause or stop it. For prefers-reduced-motion: reduce, pause animations automatically.

Text-over-Image Strategies:

StrategyContrast GuaranteePerformance
Solid overlay (rgba(0,0,0,0.5))Strong, uniformSimple, reliable
Gradient scrim (transparent → dark)Strong in text area, image visible elsewhereMore visually sophisticated
Text shadow (0 2px 4px rgba(0,0,0,0.8))Moderate, depends on imageLightweight but less reliable
Background on text (semi-transparent pill)Strong, localizedCan look dated
Dark image selection (curate only dark images)Unreliable, varies by imageFragile — avoid

The recommended approach is a gradient scrim: a CSS gradient overlay that transitions from near-opaque behind the text to transparent toward the image focal point. This provides reliable contrast while preserving image visibility.

Usage Guidelines

Usage Guidelines

Do:

  • Use fluid typography with clamp() for responsive hero titles — configure with the Font Scale Generator
  • Always provide a background-color fallback that approximates the hero image's dominant color
  • Test text contrast against the worst-case background area, not the average — use the Contrast Checker
  • Use a scrim gradient overlay for text-over-image heroes to ensure consistent contrast
  • Keep hero messaging concise: one headline, one supporting line, one primary CTA
  • Provide prefers-reduced-motion handling for video/animated heroes
  • Use loading="eager" and fetchpriority="high" for hero images — they are the LCP element
  • Include a single clear call-to-action. If you must have two, make one primary and one secondary (ghost/outline)

Don't:

  • Place critical content below a full-viewport hero on mobile — users may not realize they can scroll
  • Use auto-playing video with sound — always mute autoplay videos
  • Use text directly over busy images without an overlay — this virtually guarantees contrast failures
  • Create heroes taller than the viewport on mobile — content below becomes invisible
  • Use hero carousels/sliders — they have poor engagement rates and significant accessibility issues (see Carousel)
  • Rely on background images for conveying essential information — they're invisible to screen readers and may not load

Performance Considerations:

OptimizationImpact
Use <img> with srcset/sizes for responsive image loadingServes appropriately sized images per viewport
Use WebP/AVIF formats with JPEG fallback25–50% smaller file sizes
Add fetchpriority="high" to the hero imageBrowser prioritizes LCP image download
Inline critical CSS for the heroPrevents FOUC (flash of unstyled content)
Use aspect-ratio to prevent layout shiftReserves space before image loads (CLS improvement)

Hero Copy Hierarchy:

ElementCharacter LimitTypography
Badge/label15–20 charsSmall caps or tag style
Headline40–60 charsDisplay font, bold
Subheadline80–150 charsBody font, regular weight
Primary CTA15–25 charsButton, primary variant
Secondary CTA15–25 charsButton, ghost/outline variant

Code Snippets

html
<!-- Centered hero with gradient background -->
<section class="hero hero--centered" style="
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 80vh;
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  color: #ffffff;
  padding: 48px 24px;
  text-align: center;
">
  <div class="hero__content" style="max-width: 720px;">
    <span class="hero__badge" style="
      display: inline-block;
      padding: 4px 12px;
      background: rgba(255,255,255,0.2);
      border-radius: 9999px;
      font-size: 0.875rem;
      margin-bottom: 16px;
    ">Now in Beta</span>
    <h1 class="hero__title" style="
      font-size: clamp(2rem, 5vw, 4rem);
      line-height: 1.1;
      margin: 0 0 16px;
      font-weight: 700;
    ">Build beautiful interfaces faster</h1>
    <p class="hero__subtitle" style="
      font-size: clamp(1rem, 2vw, 1.5rem);
      line-height: 1.5;
      margin: 0 0 32px;
      opacity: 0.9;
    ">A complete design system with accessible components, design tokens, and interactive tools.</p>
    <div class="hero__actions" style="display: flex; gap: 12px; justify-content: center; flex-wrap: wrap;">
      <a href="/get-started" class="btn btn--primary btn--lg">Get Started</a>
      <a href="/docs" class="btn btn--ghost btn--lg" style="color: #fff; border: 1px solid rgba(255,255,255,0.3);">Documentation</a>
    </div>
  </div>
</section>

<!-- Split hero with image -->
<section class="hero hero--split" style="
  display: grid;
  grid-template-columns: 1fr 1fr;
  min-height: 70vh;
  align-items: center;
">
  <div class="hero__content" style="padding: 48px;">
    <h1 style="font-size: clamp(2rem, 4vw, 3.5rem); line-height: 1.1; margin: 0 0 16px;">
      Your product headline
    </h1>
    <p style="font-size: 1.25rem; color: #6b7280; margin: 0 0 32px; line-height: 1.5;">
      A compelling description of what your product does and why users should care.
    </p>
    <div style="display: flex; gap: 12px;">
      <a href="/signup" class="btn btn--primary btn--lg">Start Free Trial</a>
    </div>
  </div>
  <div class="hero__media">
    <img src="hero-image.webp" alt="" loading="eager" fetchpriority="high"
         style="width: 100%; height: 100%; object-fit: cover;" />
  </div>
</section>

<style>
@media (max-width: 768px) {
  .hero--split {
    grid-template-columns: 1fr !important;
  }
  .hero--split .hero__content { order: 1; }
  .hero--split .hero__media { order: 0; max-height: 300px; overflow: hidden; }
}
</style>
tsx
import React from 'react';

interface HeroProps {
  variant?: 'centered' | 'split' | 'fullImage' | 'minimal' | 'gradient';
  size?: 'sm' | 'md' | 'lg' | 'full';
  backgroundImage?: string;
  backgroundColor?: string;
  overlay?: boolean;
  overlayColor?: string;
  title: React.ReactNode;
  subtitle?: React.ReactNode;
  actions?: React.ReactNode;
  media?: React.ReactNode;
  mediaPosition?: 'left' | 'right';
  badge?: React.ReactNode;
  textAlign?: 'left' | 'center' | 'right';
  maxWidth?: string;
  className?: string;
}

const sizeMap = { sm: '300px', md: '50vh', lg: '80vh', full: '100vh' };

function Hero({
  variant = 'centered',
  size = 'lg',
  backgroundImage,
  backgroundColor = 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
  overlay = true,
  overlayColor = 'rgba(0,0,0,0.4)',
  title,
  subtitle,
  actions,
  media,
  mediaPosition = 'right',
  badge,
  textAlign = variant === 'split' ? 'left' : 'center',
  maxWidth = '720px',
  className,
}: HeroProps) {
  if (variant === 'split') {
    return (
      <section
        className={className}
        style={{
          display: 'grid',
          gridTemplateColumns: mediaPosition === 'right' ? '1fr 1fr' : '1fr 1fr',
          minHeight: sizeMap[size],
          alignItems: 'center',
        }}
      >
        <div style={{ padding: 48, order: mediaPosition === 'left' ? 1 : 0 }}>
          {badge && <div style={{ marginBottom: 16 }}>{badge}</div>}
          <h1 style={{ fontSize: 'clamp(2rem, 4vw, 3.5rem)', lineHeight: 1.1, margin: '0 0 16px' }}>
            {title}
          </h1>
          {subtitle && (
            <p style={{ fontSize: '1.25rem', color: '#6b7280', margin: '0 0 32px', lineHeight: 1.5 }}>
              {subtitle}
            </p>
          )}
          {actions && <div style={{ display: 'flex', gap: 12, flexWrap: 'wrap' }}>{actions}</div>}
        </div>
        <div style={{ order: mediaPosition === 'left' ? 0 : 1, overflow: 'hidden', height: '100%' }}>
          {media}
        </div>
      </section>
    );
  }

  return (
    <section
      className={className}
      style={{
        position: 'relative',
        display: 'flex',
        alignItems: 'center',
        justifyContent: 'center',
        minHeight: sizeMap[size],
        background: backgroundImage ? undefined : backgroundColor,
        backgroundImage: backgroundImage ? `url(${backgroundImage})` : undefined,
        backgroundSize: 'cover',
        backgroundPosition: 'center',
        color: '#ffffff',
        padding: '48px 24px',
        textAlign,
      }}
    >
      {overlay && backgroundImage && (
        <div
          aria-hidden="true"
          style={{
            position: 'absolute',
            inset: 0,
            background: overlayColor,
          }}
        />
      )}
      <div style={{ position: 'relative', maxWidth, zIndex: 1 }}>
        {badge && <div style={{ marginBottom: 16 }}>{badge}</div>}
        <h1 style={{ fontSize: 'clamp(2rem, 5vw, 4rem)', lineHeight: 1.1, margin: '0 0 16px', fontWeight: 700 }}>
          {title}
        </h1>
        {subtitle && (
          <p style={{ fontSize: 'clamp(1rem, 2vw, 1.5rem)', lineHeight: 1.5, margin: '0 0 32px', opacity: 0.9 }}>
            {subtitle}
          </p>
        )}
        {actions && (
          <div style={{ display: 'flex', gap: 12, justifyContent: textAlign === 'center' ? 'center' : 'flex-start', flexWrap: 'wrap' }}>
            {actions}
          </div>
        )}
      </div>
    </section>
  );
}

// Usage
function LandingPage() {
  return (
    <Hero
      variant="centered"
      size="lg"
      backgroundColor="linear-gradient(135deg, #667eea 0%, #764ba2 100%)"
      badge={<span className="badge badge--outline">Now in Beta</span>}
      title="Build beautiful interfaces faster"
      subtitle="A complete design system with accessible components, design tokens, and interactive tools."
      actions={
        <>
          <a href="/start" className="btn btn--primary btn--lg">Get Started</a>
          <a href="/docs" className="btn btn--ghost btn--lg">Documentation</a>
        </>
      }
    />
  );
}

Design Systems

Design System Implementations

Hero sections are typically application-level compositions rather than standardized design system primitives. Most design systems provide the building blocks (typography, spacing, buttons, layout) and leave hero composition to the application layer. However, some systems include hero-specific components:

Bootstrap provides the Jumbotron (deprecated in v5) which was a simple padded container with a larger heading. In Bootstrap 5, the recommended approach is composing a hero from utility classes: py-5 text-center bg-body-tertiary with responsive grid columns. Bootstrap's Examples page includes several hero templates (centered, split, image background) as copy-paste starting points.

Material Design 3 does not include a "Hero" component. MUI's approach is to compose heroes from <Box>, <Container>, <Typography>, <Stack>, and <Button>. The Material Design spec does not define a hero section pattern, as it is more of a marketing/editorial pattern than an application UI pattern.

Chakra UI does not provide a Hero component. Chakra's documentation includes hero examples built from <Container>, <Heading>, <Text>, <Stack>, and <Button>. The philosophy is that heroes are too variable in layout and content to standardize into a single component.

Tailwind UI (the commercial component library for Tailwind CSS) provides numerous hero section templates in their "Marketing > Hero Sections" category. These include: simple centered, split with image, split with screenshot, angled background, with app screenshot, with phone mockup, and dark variants. Tailwind UI represents the most comprehensive hero pattern library available, though it is template-based rather than component-based.

Ant Design does not provide a hero component. Landing page patterns are available in Ant Design Pro and Ant Design Landing (a separate page builder tool) which includes hero section templates with animated text and scroll-triggered effects.

Shadcn/ui does not include a hero component but provides all building blocks. Community-contributed hero patterns are available through the Shadcn registry and typically combine the Card, Button, and typography primitives with Tailwind utilities.

The consensus across design systems is that heroes are composed, not componentized. The building blocks that matter most for heroes are: Stack for content layout, Grid for split layouts, typography components for display headings, and Button for CTAs.

LayoutHero SectionBannerJumbotron