Design Lounge
Install

Nº 094 of 520

Asymmetric type lockup hero

A poetry-press hero: 160px italic QUARTO broken across an asymmetric 12-column grid, a 14px paragraph in the leftover cell, and one underline button.

Preview

Open full size
1280 × 800 · 6.7 KB · 104 lines

Use it

Free to use · credit appreciated

1 Once, in your project

npx skills add SusanAcharya/Design-Lounge

2 Then ask

Using the Design Lounge skill, build "Asymmetric type lockup hero" (piece hero-asymmetric-type-lockup) in my stack. Match its brief; restyle it onto my product's theme.

No skill? Paste the brief instead. It carries the numbers, tokens and behaviour.

Brief

173 lines

Build brief for a coding agent. Rebuild this piece in the reader’s stack. If they haven’t said which stack, ask once, then default to semantic HTML + CSS + a little vanilla JS. Match the numbers below; don’t “improve” them.

What it is

The top of the site for Quarto, a fictional Lisbon poetry press. The brand name is the composition: QUA sits in columns 1–8 at 160px italic Playfair Display, RTO sits in columns 6–13 on the next row, right-aligned and pulled up 28px so the two halves almost lock. A 14px Karla paragraph occupies the leftover cell (columns 9–13 of the first row), tucked against the A. One underline text button is the only CTA. Letters rise on load with a 70ms stagger; Replay and a click on the stage restart them.

Reference behaviour

  1. Initial state: warm apricot paper (#f3e4d2). A 64px nav with italic “Quarto” mark, three links (Catalogue is current), and a brick “Subscribe” on the right. Below: an 11px uppercase kicker “Poetry in print · Lisbon”.
  2. On load, body has class play. The three letters of QUA rise from translateY(108%) + opacity 0 to rest, 720ms expo-out, delays 0 / 70 / 140ms. RTO uses the same animation with a 240ms base delay (240 / 310 / 380ms).
  3. The nest paragraph fades and rises 10px over 640ms, delay 620ms. The CTA does the same, delay 780ms.
  4. Hovering the CTA turns text and underline --accent (#a33a24); the 16px arrow translates 4px right over 160ms.
  5. Nav links: hover or aria-current turns colour --ink and draws a 1px ink underline. Subscribe hover adds a 1px accent underline.
  6. Clicking Replay, or clicking the stage anywhere except a link, removes play, forces reflow, and adds play again so every entrance restarts from zero.
  7. Links with href="#" call preventDefault in the demo.
  8. Reduced motion: letters, nest and CTA render in their final position with no animation.

Structure

1280 × 800, margins 48, 12 cols, gutter 16
┌──────────┬──────────────────────────┬────────────┐
│ Quarto   │ Catalogue Authors Events │ Subscribe  │  nav 64, 1px rule
├──────────┴──────────────────────────┴────────────┤
│ —— Poetry in print · Lisbon                       │  kicker 11
│                                                   │
│ Q U A                  Twelve poets on the        │  160px italic
│                        weather of a city…         │  nest 14 / 1.55
│              R T O                                │  160px, −28px
│ Open the autumn list →                            │  underline CTA
│                                                   │
│ Vol. XII   128 pages   Edition of 800      28 €   │  meta, 1px rule
│ Autumn     Smyth-sewn  Lisbon + mail    incl. post│
│                                      [REPLAY]     │
└───────────────────────────────────────────────────┘
  • <nav aria-label="Primary"> is a 12-column grid. .mark spans 1–4, <ul> spans 5–10, .sub spans 11–13 (end).
  • <main> is the same 12-column grid, rows auto 1fr auto.
  • .kick spans 1–6. .stage spans 1–12 and is itself grid-template-columns: subgrid.
  • Visually hidden <h1 class="sr">Quarto</h1>. Display letters live in .a (columns 1–8) and .b (columns 6–13), each letter a <span style="--i">, aria-hidden.
  • .nest is a <p> at columns 9–13, grid-row: 1, align-self: end.
  • .cta is a text <a> at columns 1–6 with an inline SVG arrow.
  • .meta is four <div>s on the same 12-column subgrid. Replay is position:absolute; right:48px; bottom:86px inside main (position:relative).

Tokens

:root {
  --paper: #f3e4d2;            /* page */
  --paper-2: #ead6c0;          /* reserved */
  --ink: #27170f;              /* primary type */
  --ink-2: #6a4e3e;            /* nest, nav rest */
  --ink-3: #9a7d6a;            /* kicker, meta, replay */
  --line: rgba(39, 23, 15, .16);
  --accent: #a33a24;           /* subscribe, CTA hover */
  --accent-soft: #e8c4b4;
  --serif: "Playfair Display", Georgia, "Times New Roman", serif;
  --sans: "Karla", system-ui, sans-serif;
  --gutter: 48px;
  --gap: 16px;
  --nav-h: 64px;
  --display: 160px;
  --t-micro: 160ms;
  --t-letter: 720ms;
  --t-copy: 640ms;
  --stagger: 70ms;
  --ease: cubic-bezier(.2, .7, .2, 1);
  --expo: cubic-bezier(.16, 1, .3, 1);
}

Typography

RoleFamilySizeWeightLine-heightTrackingCase
LockupPlayfair Display160pxitalic 7000.82−0.045emUPPERCASE
Brand markPlayfair Display22pxitalic 5001−0.02emTitle
Nest copyKarla14px4001.550sentence
CTAKarla15px50010sentence
NavKarla13px5001+0.04emTitle
KickerKarla11px5001+0.18emUPPERCASE
MetaKarla12px5001.4+0.04emmixed
ReplayKarla11px5001+0.12emUPPERCASE

Motion

ElementTriggerPropertyFrom → ToDurationEasingDelay
QUA letterload / replaytranslateY, opacity108% + 0 → rest720ms--expoi × 70ms
RTO letterload / replaytranslateY, opacity108% + 0 → rest720ms--expo240ms + i × 70ms
Nestload / replayopacity, translateY0 + 10px → rest640ms--ease620ms
CTAload / replayopacity, translateY0 + 8px → rest640ms--ease780ms
CTA arrowhovertranslateX0 → 4px160ms--ease0
Nav / CTAhovercolor, borderink-2 → ink/accent160ms--ease0

Replay: body.classList.remove('play'); void body.offsetWidth; body.classList.add('play'). Reduced motion: no keyframes; letters and copy start at rest, opacity 1.

States

  • Nav link hover / current: colour --ink, 1px ink bottom border. Current route uses aria-current="page".
  • Subscribe hover: 1px --accent underline.
  • CTA hover: colour and underline --accent; arrow +4px X.
  • Replay hover: colour and border --ink.
  • Focus-visible: 2px --accent outline, 4px offset, on every link and the Replay button.
  • Reduced motion: final frame, no rise.

Accessibility

  • The visible lockup is aria-hidden. Screen readers get the visually hidden <h1>Quarto</h1> (clipped 1×1).
  • Tab order: brand, Catalogue, Authors, Events, Subscribe, CTA, Replay.
  • Contrast: --ink on --paper is well above 4.5:1. --ink-2 (#6a4e3e) on paper is about 6.5:1. --ink-3 is used only for 11–12px captions that repeat other information.
  • Hit targets: Replay padding makes it ≥ 32px tall; pad to 40px on touch. CTA is a text link with 8px vertical padding.

Responsive rules

  • ≥ 1280: as specified. --display stays 160px.
  • 1024–1279: --display: 12.5vw (still ~128–160px). Nest stays columns 9–13.
  • 768–1023: stack the lockup. QUA full width, nest below it (not beside), RTO left-aligned on the next row. Nav links collapse to the mark plus Subscribe.
  • < 640: --display: 72px. Meta becomes a 2×2 grid. Hide Replay; clicking the lockup still replays.

Acceptance checklist

  • QUA is 160px italic 700 Playfair, columns 1–8; RTO is the same size, columns 6–13, text-align: right, margin-top: -28px.
  • Nest paragraph sits in columns 9–13 of the first lockup row, 14px/1.55 Karla, --ink-2.
  • Letters rise 108% → 0 over 720ms on cubic-bezier(.16,1,.3,1) with a 70ms stagger; RTO is delayed 240ms.
  • Exactly one CTA: underline text plus 16px arrow, no filled button.
  • Replay and a click on empty stage restart the entrance; clicking a link does not.
  • <h1> announces “Quarto”, not six letters.
  • Focus rings are 2px #a33a24 with a 4px offset.
  • Reduced motion shows the finished lockup with no movement.
  • Palette is apricot paper #f3e4d2, walnut #27170f, brick #a33a24 — not Fraunces, not amber-on-black.
  • Only Playfair Display and Karla load.

Implementation notes

Subgrid keeps the nest cell on the same 12 columns as the nav. Without it the leftover cell drifts:

main, nav, .stage, .meta {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  column-gap: 16px;
}
.stage, .meta { grid-column: 1 / -1; grid-template-columns: subgrid; }
.a { grid-column: 1 / 8; }
.nest { grid-column: 9 / 13; grid-row: 1; align-self: end; }
.b { grid-column: 6 / 13; text-align: right; margin-top: -28px; }

Replayable letter rise — letters start translated; .play attaches the animation:

.a span, .b span { display: inline-block; transform: translateY(108%); opacity: 0; }
.play .a span, .play .b span {
  animation: rise 720ms cubic-bezier(.16,1,.3,1) forwards;
  animation-delay: calc(var(--i) * 70ms + var(--base, 0ms));
}
@keyframes rise { to { transform: none; opacity: 1; } }

Do not put the nest <p> inside the <h1>. It is invalid HTML and it steals the heading from AT. Keep a clipped <h1> and aria-hidden on the display letters.

Common mistakes: line-height: 1 on 160px italic (the tails clip), giving RTO a positive margin so the lockup falls apart, filling the CTA.

Details

Palette
Type
Playfair Display · Karla
Motion
Rich motion
Build
One session
Designed bySusan AcharyaKathmandu

Studied

Haunted Boulder City

Pin the screen and let scroll turn the pages. Only the line you are on gets to shout.

All sources