s72

CSS + JSNo build stepv0.1

Write plain HTML. Get the whole design.

s72 is a design library from the Munich 1972 Olympics, set for the web: flat colour fields, ticket stubs, a generated pattern and an editorial serif. You write semantic HTML. A few data attributes pick the variants.

cp dist/s72.css dist/s72.js your-site/

  • Get started
  • See every component
  • Start

    Copy dist/s72.css and dist/s72.js into your site, link them, and set the config on <html>. No build step and no runtime dependencies.

    index.html
    <html data-pattern="5">
    <head>
      <link rel="stylesheet" href="s72.css">
      <script src="s72.js" defer></script>
    </head>
    <body>
      <header><a href="/">Brand</a><nav>…</nav></header>
      <main>
        <section data-hero><h1>Hello</h1><p>…</p></section>
      </main>
      <footer>…</footer>
    </body>
    </html>

    Line 1 is the whole config: a pattern number. Leave the rest out and you get the plum palette, Newsreader, a flat surface, paper grain and stamps; add data-palette, data-type, data-surface, data-theme, data-texture="none" or data-stamps="off" to change any of them. From npm: npm i s72, then import 's72' for the module and s72/s72.css for the stylesheet.

    Config

    Set it on <html>, or in script with S72.config({…}). Try it here: the whole page changes.

    config.js
    S72.config({
      palette: 'mist',        // plum · mist · cream · munich
      type: 'instrument',     // newsreader · bodoni · instrument · grotesk
      pattern: 12,            // any whole number; 25 families
      theme: 'dark',          // light · dark · system
      surface: 'offset',      // flat · offset
      texture: 'none',        // none turns the paper grain off
      stamps: false,          // false turns the stamps off
      fonts: true             // false to self-host the fonts
    });
    AttributeValues
    data-paletteplum, mist, cream, munich
    data-typenewsreader, bodoni, instrument, grotesk
    data-patternany whole number
    data-themelight, dark, or leave out to follow the system
    data-surfaceflat, offset
    data-texturegrain; none turns the grain off
    data-stampsoff turns the stamps off

    Elements

    Plain HTML, styled as it is. No classes needed.

    Eyebrow label

    Heading with italic

    Body text with a link, inline code, a key ⌘ K, and chips: Default Go Stop Info Earth

  • Form

    atlas build --watch

    Controls

    Segmented

    Theme

    elements.html
    <mark data-tone="go">Allowed</mark>
    <button data-variant="line">Line</button>
    <p data-command><code>atlas build --watch</code></p>   <!-- s72.js adds the copy button -->
    <input type="checkbox" role="switch">
    <input type="range" min="0" max="90" value="30">
    <fieldset data-segmented><legend>Mode</legend><label><input type="radio" name="m" checked> Build</label>…</fieldset>

    Components

    Compound pieces, each built from ordinary elements plus one data attribute.

    Tone panels

    softlight accent
    goallowed, success
    stopdenied, danger
    infonotice
    earthneutral, result
    inkdarkest

    Tickets

    A ticket

    The <aside> is the stub and carries the pattern.

    Every other ticket mirrors

    Inside data-tickets, even tickets flip sides.

    tickets.html
    <div data-tickets>
      <article data-ticket data-tone="go">
        <aside><span class="stub-label">Stub</span></aside>
        <h3>A ticket</h3><p>…</p>
      </article>
    </div>

    Cards and pattern edges

    Top

    data-edge="top"

    Edge

    Left

    data-edge="left"

    Edge

    Fade

    data-fade, behind the text

    Fade
    Statatlas 1.4.012s

    Policy list and stamp

    Pages 182 built
    Fresh
    Links 3 missing
    Failed
    A <dl> of dt/dd pairs in a <figure>. The <figcaption> is the footnote.
    data-stamps

    Stamps follow actions

    A button with data-stamp stamps its target after a click. Nothing shows before that.

  • State

    A chosen thing is marked

    state.html
    <button role="tab" aria-selected="true">Overview</button>
    <a href="/docs" aria-current="page">Docs</a>
    <button aria-pressed="true">Pressed toggle</button>

    Selected tabs and current links are underlined; a pressed toggle fills with ink. State is ARIA, never a class.

    Table

    EntryKindRecordTime
    00001pageRendered guide/index.md14 ms
    00002missingLink not found: /guide/old—
    00003result182 built, 0 failed1.94 s

    Code view

    main.rs
    use std::fs;
    
    fn main() {
        // atlas writes each rendered page into the output folder
        let n = fs::write("notes.txt", "hello").is_ok();
        println!("{n}");
    }

    data-lang picks the colouring (sh, js, html, css, rust, toml, json). data-mark="3" or "2,5-7" marks lines.

    Patterns

    Every whole number is a pattern. The number picks one of 25 geometric families and seeds its sizes, so 5, 30 and 55 are all truchet arcs and each is different. Click one to use it.

    Tokens

    Every value is a CSS custom property on :root. Override any of them, on the page or on a single element.

    overrides.css
    :root {
      --s72-max: 1320px;           /* page width */
      --s72-gap: 16px;             /* space between cards */
      --s72-go: #2f8f4e;           /* any tone */
      --s72-display: "Fraunces", Georgia, serif;
    }
    .pricing { --s72-soft: #f6c61a; --s72-soft-fg: #1c2b3c; }   /* scoped */
    GroupTokens
    Surfaces--s72-paper --s72-card --s72-line --s72-hover --s72-bad
    Text--s72-fg --s72-fg-2
    Tones--s72-soft --s72-go --s72-stop --s72-info --s72-earth --s72-ink (each with -fg)
    Fills--s72-solid --s72-btn --s72-hero (each with -fg)
    Type--s72-display --s72-body --s72-mono --s72-display-scale --s72-s1…s7
    Layout--s72-max --s72-gutter --s72-gap --s72-section
    Pattern--s72-tex --s72-tex-size --s72-tex-light --s72-tex-dark
    Code--s72-code-bg --s72-code-gutter --s72-code-inline --s72-code-mark --s72-tok-*