Hero

.hero

Hero — the band at the top of a page that says what the page is and gives you the one thing to do with it.

Examples

The band

View “The band” as

Milan

When is the next one

Type the name of your stop and we will tell you how many minutes away the next tram, bus or train is.

<section class="hero" aria-labelledby="hero-a">
  <p class="hero-eyebrow">Milan</p>
  <h1 class="hero-title" id="hero-a">When is the next one</h1>
  <p class="hero-lead">Type the name of your stop and we will tell you how many
  minutes away the next tram, bus or train is.</p>
  <div class="hero-actions">
    <a class="btn btn-primary" href="#stops">Find a stop</a>
    <a class="btn" href="#lines">Browse the lines</a>
  </div>
</section>

The band is full-bleed and does not centre its contents: put your own width-limiting wrapper inside it, the same way you would inside a navbar.

Everything else is subtraction — no border, no radius, no shadow, and one heading doing the work a box used to do.

The full-contrast field

View “The full-contrast field” as

Open data

Everything happens in your browser

No account, no tracking, no server holding your search.

<section class="hero hero-tall" data-theme="dark" aria-labelledby="hero-b">
  <p class="hero-eyebrow">Open data</p>
  <h1 class="hero-title" id="hero-b">Everything happens in your browser</h1>
  <p class="hero-lead">No account, no tracking, no server holding your search.</p>
  <div class="hero-actions">
    <a class="btn btn-primary" href="#start">Start</a>
    <a class="btn btn-outline" href="#sources">Where the data comes from</a>
  </div>
</section>

The reversed-out poster treatment is data-theme on the section, not a modifier class.

A class flipping two colours would leave every .btn and .input inside the band reading the page's foreground against the band's background; the mode axis re-resolves all of them, because it is the same mechanism the light/dark toggle uses. On a dark page, write data-theme="light".

One thing to do

View “One thing to do” as

Search 2,435 stations

Part of the name is enough.

<section class="hero" aria-labelledby="hero-c">
  <h1 class="hero-title" id="hero-c">Search 2,435 stations</h1>
  <search class="search hero-search">
    <label class="sr-only" for="hero-q">Station</label>
    <svg class="icon search-icon" aria-hidden="true"><use href="#icon-search"></use></svg>
    <input class="input search-input" id="hero-q" name="q" type="search"
           placeholder="Milano Centrale, Bosco, Riccione…" />
  </search>
  <p class="hero-note">Part of the name is enough.</p>
</section>

.hero-search caps the field at 34rem. A search box stretched across a desktop window reads as a page-wide bar rather than as a thing to type in — and a hero that carries a field, five filter chips and a select is a control panel, which is the shape this block exists to avoid.

An inner page

View “An inner page” as

Lines

Every line in the network, with its stops and its timetable.

<section class="hero hero-sm" aria-labelledby="hero-d">
  <h1 class="hero-title" id="hero-d">Lines</h1>
  <p class="hero-lead">Every line in the network, with its stops and its timetable.</p>
</section>

A third of the height and one step down the type scale, for a section index or a detail page.

The tall version above a table of results is a page that starts twice. .hero-plain goes further and drops the ground and the rule altogether.

Tokens 19

Level 2, declared on .hero itself. Set any of them on that selector to restyle this block without touching the skin.

Level 2 tokens declared by hero
TokenDefault
--hero-actions-gapvar(--space-3)
--hero-eyebrow-colorvar(--color-on-surface-muted)
--hero-eyebrow-font-sizevar(--font-size-xs)
--hero-lead-colorvar(--color-on-surface-muted)
--hero-note-colorvar(--color-on-surface-muted)
--hero-note-font-sizevar(--font-size-sm)
--hero-padding-blockvar(--space-12) var(--space-10)
--hero-padding-inlinevar(--space-4)
--hero-search-size34rem
--hero-title-font-familyvar(--font-primary)
--hero-title-font-sizevar(--font-size-3xl)
--hero-lead-font-size1.125rem
--hero-lead-measurevar(--measure)
--hero-bgvar(--color-surface-sunken)
--hero-border-colorvar(--color-border-subtle)
--hero-border-widthvar(--border-width)
--hero-colorvar(--color-on-surface)
--hero-title-colorvar(--color-on-surface)
--hero-title-font-weightvar(--font-weight-normal)

Variants and states

Variants

  • .hero-plain
  • .hero-sm
  • .hero-tall

Inside it

  • .hero-actions
  • .hero-eyebrow
  • .hero-lead
  • .hero-note
  • .hero-search
  • .hero-title

State it reads

None.

Before you ship it

What you have to do 5 requirements

  1. Put your own width-limiting wrapper inside the band, and set --hero-padding-inline: 0 when you do. The hero is full-bleed on purpose and does not centre its contents; without a wrapper the title runs the full width of a desktop window. The gutter here exists for the page that has no wrapper, so that nothing touches the edge of a phone — and it adds to your wrapper's own padding, which on a narrow screen indents the title by twice what the rest of the page is indented by. One line, in your stylesheet, on .hero.
  2. .hero-title goes on the page's <h1>. It styles a heading, it does not make one: a <div class="hero-title"> is a page with no first-level heading, which is how a screen-reader user loses the outline of the site. One <h1> per page, and in a hero it is this one.
  3. .hero-eyebrow is not a heading. It is a label above the title — a <p>. Marking it up as an <h2> puts a heading above the <h1> and inverts the document outline.
  4. Name the section. <section class="hero" aria-labelledby="…"> pointing at the title, or drop the <section> and let the band be a <header>. A <section> with no accessible name is a landmark nobody can navigate to.
  5. Check the contrast if you set --hero-bg to a brand colour. The default ground is a skin token whose pair is audited; a colour you chose is not.

src/css/blocks/hero.css · npx mostlycss add hero