A small technical field note
How the
pieces
behave.
Werkraum’s site is a short lesson in a very Bauhaus proposition: a small set of clear forms can make a surprising number of worlds.
01 / Concept
A school should look like an invitation.
Werkraum is imagined as a Saturday design school in Grünerløkka for children who notice things: the way a chair balances, the red on a bus stop, the sound a cardboard tube makes when it rolls under a table. Its copy is practical and observant because the school is about giving those observations a place to grow.
The art direction borrows the economy, not the severity, of Bauhaus exercises. A paper-white field, a geometric sans, a strict black rule and four primary colours give the page enough discipline that a yellow circle or crooked square can feel delighted rather than decorative.
02 / Signature technique
One tray. Seven beats.
The hero is not a video or a single pre-drawn illustration. Twenty direct SVG primitives are created once, then placed using CSS transforms. As the tall scroll section advances, they move through seven discrete cues: loose parts, a face, loose parts, a building, loose parts, a chair, loose parts.
Each cue has a distinct scatter arrangement, so the assembled images feel discovered rather than slid apart. The transform delay follows the piece index and the cubic-bezier curve runs past the destination before settling. That small overshoot keeps the system playful without using 3D or a canvas.
parts
01
face
02
parts
03
building
04
parts
05
chair
06
parts
07
Actual moving part
Both the target coordinate and the spring delay are applied to each SVG primitive. The positions are converted from the 600 × 480 viewBox to the rendered SVG size before the CSS transform is set. The updater only queues work while the stage is near the viewport and the document is visible.
function positionPieces(nextState) {
const width = svg.clientWidth;
const height = svg.clientHeight;
if (!width || !height) return;
const scaleX = width / 600;
const scaleY = height / 480;
elements.forEach((el, i) => {
const composition = pieces[i][3];
const point = nextState % 2 === 0
? scatter[Math.min(3, nextState / 2)][i]
: composition[(nextState - 1) / 2];
el.style.transitionDelay = reducedMotion ? '0ms' : `${(i % 7) * 38 + Math.floor(i / 7) * 18}ms`;
el.style.transform = `translate(${point[0] * scaleX}px,
${point[1] * scaleY}px) rotate(${point[2]}deg)`;
});
}
03 / Palette & type
Colour has a job to do.
The palette is deliberately finite: the colour moves around the page to make modules distinguishable and to let the composition read instantly at a distance. Black stays reserved for structure and legibility; paper white gives the small forms a place to breathe.
#E63329
#005BBB
#F7C600
#101010
#FFFDF6
Display / body
Josefin Sans
Josefin Sans, Futura, Century Gothic, sans-serif
Utility / labels
Space Mono, monospace
04 / Iteration log
Three deliberate passes.
Pass 1 — corrections
- Scroll compositor: corrected triangle pieces to real SVG polygons, then added zero-size guards, resize observation, visibility handling and an intersection gate, so SVG transforms only queue while the assembly is near the viewport and the tab is visible.
- Motion: connected the live reduced-motion preference to the transform delay and disabled the remaining playful transitions in the reduced-motion stylesheet.
- Small screens: reduced the 768px hero type scale and capped the stage by viewport height, keeping the title, prompt and SVG in the sticky frame instead of clipping the composition.
- Access: added skip links, 44px minimum targets for navigation links, hidden decorative SVG children, and higher-contrast blue or black text wherever the original red-on-paper pairing fell short.
- Assets: confirmed that the site uses no raster, canvas or third-party JavaScript assets. The only external resource is the permitted Google Fonts stylesheet; layout falls back to Futura-lineage local fonts if it is unavailable.
Pass 2 — design depth
- Repeated program cards: the old 2 × 2 run gave every course the same pose. On wide screens it is now an asymmetric three-column composition: Shape Scouts becomes a broad yellow anchor, Picture Machine drops its form to the lower edge, and Big Works stretches into a two-part red banner. The simpler two-column and one-column layouts return before the cards become cramped.
- Hero restraint: the headline had an accidental last-line rhythm and the composition was held politely beside it. The four-line lock-up now sets the words intentionally, with tighter display tracking, a larger scale contrast and a stage that pushes beyond its grid toward the right edge while remaining clipped inside the sticky scene.
- Unchosen rhythm: section spacing came from several near-miss values, and the progress diamonds still used browser-default easing. An eight-point scale now drives the major insets and section intervals; the diamond cue has a spring curve matching the SVG arrivals, so every movement has the same playful logic.
Pass 3 — complexify
- A second invitation: the materials grid described the school well but did not let a visitor participate. The new five-minute workbench lets the same eight SVG pieces become a lamp, kite or robot through real buttons, with the same overshooting transform language as the hero. It is deliberately a small prompt, not a game bolted on beside the school.
- The useful blank: “Clear the table” is a real fourth state, not a dead end. Pieces settle at the edges at low opacity, the live message names what happened, and every prompt remains available by keyboard. It turns the empty state into permission to begin again.
- Finish work: added matching Open Graph metadata, tightened the last bits of copy, and kept all presentation CSS inline so there is no unstyled first paint. The workbench has resize-aware coordinates, spring delays only when motion is allowed, high-contrast focus treatment and a one-column mobile fallback before its controls become crowded.