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 band" aria-labelledby="hero-a">
  <div class="center">
    <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>
  </div>
</section>

The wrapper inside is not optional and it is not only about width.

A hero is a band that paints, so it contains — and the column's margin-block is what becomes the room inside the colour. That is why this block declares no padding-block at all: a padding would stop the collapse and add to the margin instead of resolving with it. Everything else is subtraction — 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>

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. A size sets the type and nothing else: the room above and below is the margin of the column inside the band, the same for every band on the page. .hero-plain goes further and drops the ground and the rule altogether.

Tokens 24

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-input-bgvar(--color-surface)
--hero-lead-colorvar(--color-on-surface-muted)
--hero-note-colorvar(--color-on-surface-muted)
--hero-note-font-sizevar(--font-size-sm)
--hero-padding-block0
--hero-padding-inline0
--hero-title-font-familyvar(--font-primary)
--hero-title-font-sizevar(--font-size-3xl)
--hero-trail-gapvar(--space-4)
--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-medium)
--hero-title-letter-spacingvar(--letter-spacing-title)
--hero-title-line-heightvar(--line-height-tight)
--hero-control-gapvar(--space-6)
--hero-search-size34rem

Variants and states

Variants

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

Inside it

  • .breadcrumb
  • .combobox-input
  • .hero-actions
  • .hero-control
  • .hero-eyebrow
  • .hero-lead
  • .hero-note
  • .hero-search
  • .hero-title
  • .input
  • .search-input
  • .select

State it reads

None.

Before you ship it

What you have to do 6 requirements

  1. Put your own width-limiting wrapper inside the band. 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. There is nothing else to do: the band ships no inline gutter, so your wrapper's padding is the only one and the title lines up with the rest of the page.
  2. Without a wrapper, ask for the gutter: --hero-padding-inline: var(--space-4) on .hero. A band with loose text in it and no gutter puts that text against the edge of a phone. This is the way round it is because the wrapper is the ordinary case and the loose text is the exception — the other way round cost three consumers a title indented by twice the page's own gutter, silently, for weeks.
  3. .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.
  4. .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.
  5. 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.
  6. 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