Design Lounge
Install

Nº 096 of 520

Bauhaus composition hero

A summer-school hero whose primary-colour circle, square, triangle and half-disc rearrange into three compositions on click, beside a 136px grotesk headline.

Preview

Open full size
1280 × 800 · 9.6 KB · 153 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 "Bauhaus composition hero" (piece hero-bauhaus-composition) 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

206 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 a website for a fictional design summer school, Werkhalle. On the left is a 136px black Archivo headline (“Shape / is a / verb.”, with the last word in red), a short lede, a blue CTA and a three-cell stat row. On the right is a 560px square “poster” holding seven flat shapes in red, blue, yellow and black, printed with mix-blend-mode: multiply so overlaps darken the way overprinted ink does. Clicking the poster, or one of three Roman-numeral buttons, rearranges the same seven shapes into a different composition. Every shape moves, resizes and rotates on a 900ms expo-out curve with a 60ms stagger. What makes it worth copying: one set of DOM nodes, three coordinate tables, and the motion does all the work.

Reference behaviour

  1. Initial state: composition I (“Weight”) is shown. The big red circle sits top-left, a black half-disc and ring top-right, a blue square bottom-right, a yellow triangle under the circle, and a black bar along the bottom. The caption reads “I / III · Weight · The circle anchors the corner.” and button I is pressed.
  2. The grid behind the shapes (70px squares, 1px --line) shows through every shape because of multiply.
  3. Click anywhere on the poster: the poster advances to the next composition (I → II → III → I).
  4. During the change, each shape transitions transform (translate + rotate), width and height over 900ms with cubic-bezier(.16,1,.3,1). Shape n starts n × 60ms late (0–360ms across seven shapes).
  5. Composition II (“Tension”): one 18 × 512px vertical bar splits the poster; the square tilts 12°, the half-disc flips 180° into a bowl, the circle drops bottom-right.
  6. Composition III (“Rotation”): the bar crosses the poster at −32°, the square turns 45° into a diamond, the triangle points down, the half-disc stands on its side (90°).
  7. Buttons I / II / III jump straight to that composition. Their aria-pressed reflects the current composition.
  8. The caption updates its number, title and one-line description as the shapes move. It is a polite live region.
  9. Clicking during a transition simply retargets: the CSS transitions pick up from the current in-flight values.
  10. Nav links underline on hover (2px, 5px offset). The CTA turns from blue to black on hover; “Apply” in the nav turns red.

Structure

1280 × 800
┌──────────────────────────────────────────────────────────────────────────────┐
│ ●■▲ Werkhalle                     Programme Faculty Archive Visit  [APPLY]   │ 64 nav, 1px ink rule
├──────────────────────────────────────────────────────────────────────────────┤
│ S │ [FORM][COLOUR][TYPE]                  ┌──────────────── 560 ─────────────┐│
│ U │ Shape                                 │ grid 70px                        ││
│ M │ is a              136px / .84         │   ●        ◗                     ││
│ M │ verb. (red)                           │       ○                          ││
│ E │ lede 16px, 430px measure              │   ▲     ■                        ││
│ R │ [Apply by 31 January →]  Read the…    │ ▬▬▬▬▬▬▬▬▬▬▬▬     CLICK TO RECOMP ││
│   │ ─────────────────────────             └──────────────────────────────────┘│
│   │ 06 weeks │ 60 places │ €1,480         I / III  Weight  desc   [I][II][III] │
└──────────────────────────────────────────────────────────────────────────────┘
 56px gutters · columns: 1fr | 560px · gap 72px · hero padding 40 56 36
  • <nav aria-label="Main">: logo link (three 14px marks: red disc, blue square, yellow triangle; then “Werkhalle” 18/900), <ul> of four links, black “Apply” link.
  • <main class="hero">: two-column grid.
    • .copy: vertical rotated label (writing-mode: vertical-rl; rotate(180deg)), a kicker of three outlined mono tags, <h1>, .lede, .ctas (blue button + underlined mono link), .meta (3-column stat grid pushed to the bottom with margin-top: auto).
    • .side: <button class="canvas"> containing seven <span class="shape"> children plus a hint label; then .caption with the live text and a role="group" of three aria-pressed buttons.

Tokens

:root {
  /* neutrals: cool-warm grey paper, near-black ink */
  --bg: #ecebe6;          /* page */
  --canvas-bg: #f4f3ef;   /* poster ground */
  --ink: #141414;         /* text, rules, black shapes */
  --ink-2: #4a4944;       /* lede, caption */
  --ink-3: #77756e;       /* meta labels (11px mono) */
  --line: #cfcdc5;        /* poster grid, stat dividers */

  /* primaries */
  --red: #e1341e;         /* circle, "verb.", nav Apply hover */
  --blue: #1f4fbf;        /* square, CTA, focus ring */
  --yellow: #f2b705;      /* triangle, dot */

  /* type */
  --sans: "Archivo", system-ui, sans-serif;
  --mono: "IBM Plex Mono", ui-monospace, monospace;
  --fs-display: 136px;
  --fs-stat: 30px;
  --fs-lede: 16px;
  --fs-nav: 14px;
  --fs-label: 11px;

  /* layout */
  --nav-h: 64px;
  --canvas: 560px;
  --grid-cell: 70px;
  --gutter: 56px;
  --ring-border: 16px;
  --radius: 0;            /* everything is square-cornered */

  /* motion */
  --t-micro: 160ms;
  --t-shape: 900ms;
  --stagger: 60ms;
  --ease: cubic-bezier(.2, .7, .2, 1);
  --expo: cubic-bezier(.16, 1, .3, 1);
}

Typography

RoleFamilySizeWeightLine-heightTrackingCase
HeadlineArchivo136px9000.84−0.06emsentence
LogoArchivo18px9001−0.03emtitle
Nav linksArchivo14px5001.50title
LedeArchivo16px4001.50sentence
CTAArchivo15px8001−0.01emsentence
Stat valueArchivo30px8001−0.04emnumerals
Caption titleArchivo15px8001.3−0.01emtitle
Kicker tagsIBM Plex Mono12px5001+0.12emUPPERCASE
Vertical labelIBM Plex Mono11px5001+0.18emUPPERCASE
Stat labelIBM Plex Mono11px4001.4+0.10emUPPERCASE
Caption bodyIBM Plex Mono12px4001.40sentence

Pull the headline 6px left (margin-left: -6px) so the S optically aligns with the lede.

Motion

ElementTriggerPropertyFrom → ToDurationEasingDelay
each .shapecomposition changetransform (translate, rotate)previous coords → next coords900ms--expoindex × 60ms
each .shapecomposition changewidth, heightprevious size → next size900ms--expoindex × 60ms
numeral buttonshover / pressedbackgroundtransparent → #dcdad3 / ink160ms--ease0
CTAhoverbackground--blue → --ink160ms--ease0

Composition tables, as [x, y, w, h, rotate°] on the 560px poster:

ShapeI · WeightII · TensionIII · Rotation
circle (red)42, 42, 310, 310, 0270, 250, 250, 250, 0180, 170, 210, 210, 0
triangle96, 280, 250, 230, 040, 300, 250, 220, 0310, 40, 210, 190, 180
square (blue)300, 250, 218, 218, 060, 60, 170, 170, 1262, 370, 140, 140, 45
half-disc300, 42, 218, 109, 0290, 70, 230, 115, 18024, 80, 260, 130, 90
ring392, 150, 96, 96, 0110, 190, 60, 60, 0380, 360, 140, 140, 0
bar (black)42, 500, 476, 18, 0252, 24, 18, 512, 020, 272, 520, 18, −32
dot (yellow)230, 200, 44, 44, 0430, 40, 70, 70, 0120, 40, 40, 40, 0

Reduced motion: shape transitions drop to 1ms with no stagger; the composition still changes and the caption still updates.

States

  • Poster hover: cursor pointer; the hint “CLICK TO RECOMPOSE” stays in the bottom-right at all times (10px mono, on a --canvas-bg chip so it is legible over shapes).
  • Poster focus-visible: 2px --blue outline, 3px offset.
  • Numeral button pressed: ink background, --bg text. Unpressed hover: #dcdad3.
  • Nav link hover: 2px underline at 5px offset.
  • CTA hover: background ink. Nav “Apply” hover: background red.
  • Mid-transition: no disabled state; clicks retarget.

Accessibility

  • The poster is a real <button> labelled “Rearrange composition” and aria-describedby the caption, so screen readers hear the current composition name.
  • The caption is aria-live="polite"; it announces “II / III Tension One bar holds everything up.” on change.
  • Numeral buttons sit in role="group" aria-label="Choose composition" and use aria-pressed.
  • Shapes are decorative spans inside the button; the vertical date label is aria-hidden because the dates are decorative here.
  • Focus order: logo → four nav links → Apply → CTA → syllabus link → poster → I → II → III.
  • Contrast: --ink-2 on --bg is 8.4:1; --ink-3 (used only for 11px uppercase mono labels) is 4.5:1; white on --blue is 7.2:1.
  • Numeral buttons are 44 × 36px; CTA is 52px tall.

Responsive rules

  • ≥ 1280: as specified; the poster is a fixed 560px square.
  • 1024–1279: keep two columns; scale the poster to min(560px, 44vw) by multiplying coordinates by canvas / 560 (store coordinates in poster units, not px); headline 112px.
  • 768–1023: stack: copy first, poster full-width below (max 560px), headline 112px, meta row stays 3 columns.
  • < 640: headline 72px, poster 100vw − 48px square, caption wraps under the numeral buttons, nav links collapse into a “Menu” button.

Acceptance checklist

  • The headline is 136px Archivo 900 at line-height 0.84 and −0.06em tracking; “verb.” is #E1341E.
  • The poster is exactly 560 × 560px with a 1px ink border and a 70px grid.
  • Seven shapes render with mix-blend-mode: multiply; the grid is visible through them.
  • Clicking the poster cycles I → II → III → I.
  • Each shape animates transform, width and height over 900ms with cubic-bezier(.16,1,.3,1) and a 60ms per-shape stagger.
  • The coordinates match the composition table.
  • Numeral buttons jump to their composition and expose aria-pressed.
  • The caption number, title and description update and are announced politely.
  • No shape leaves the poster bounds in any composition (overflow hidden as a safety net).
  • With reduced motion, compositions switch instantly.
  • All interactive elements show a visible 2px blue focus ring.
  • Nothing in the stat row collides with the CTA row at 1280 × 800.

Implementation notes

One set of nodes, many layouts. Do not render three SVGs and cross-fade. Keep seven absolutely positioned spans at left: 0; top: 0 and drive them only with inline transform, width and height:

const C = [{ s: { c: [42, 42, 310, 310, 0], b: [42, 500, 476, 18, 0] /* … */ } }];
function apply(k) {
  shapes.forEach(el => {
    const [x, y, w, h, r] = C[k].s[el.dataset.k];
    el.style.width = w + 'px'; el.style.height = h + 'px';
    el.style.transform = `translate(${x}px, ${y}px) rotate(${r}deg)`;
  });
}

Stagger with a custom property, so the delay lives in CSS and reduced motion can zero it:

.shape { position: absolute; left: 0; top: 0; mix-blend-mode: multiply;
  transition: transform var(--t-shape) var(--expo), width var(--t-shape) var(--expo),
              height var(--t-shape) var(--expo);
  transition-delay: calc(var(--i) * var(--stagger)); }
.t { background: var(--yellow); clip-path: polygon(50% 0, 100% 100%, 0 100%); }
.h { background: var(--ink); border-radius: 999px 999px 0 0; } /* height = width / 2 */

Shapes that keep their identity while resizing: the triangle uses clip-path (scales with the box), the half-disc uses a 999px top radius on a box whose height is half its width, and the ring is a transparent circle with a 16px border. Rotation happens around the box centre, so a 90° half-disc needs its x adjusted by (w − h) / 2 if you want it flush to an edge.

Common mistakes: putting isolation on the shapes instead of the poster (blend modes then mix with the page), animating left/top instead of transform (janky), and running the first apply() after a paint (the shapes fly in from 0,0 on load).

Details

Palette
Type
Archivo · IBM Plex Mono
Motion
Rich motion
Build
One session
Designed bySusan AcharyaKathmandu

Studied

Moremedia

Set the services as tall labels. Open one, and keep the rest as type.

All sources