Skip to content

PRIMITIVE

Scene

A picture behind the words. Two classes and an image element — the section it lands on keeps every decision it already had, and the photograph is mixed into whatever surface that section is sitting on.

A picture behind a hero

Nothing about the hero changed. The image is a sibling of the body, and scene-media lifts it out of flow.

FIELD NOTES · ISSUE 04

Everything worth building runs out into the fog first.

The photograph is mixed into whatever surface this band is sitting on, at the strength the theme states — so this paragraph reads at the ratio it would have had on a plain section. Switch the theme at the top of the page: the picture has not changed, and what it is mixed into has.

HTML
<!-- The section is untouched. The picture is a SIBLING of the body: `scene-media`
     lifts it out of flow and puts it one layer down, so the hero goes on being
     a hero and nothing about its markup has to change. -->
<section class="hero scene shell" style="width:100%">
  <img class="scene-media" src="/scenery/causeway.webp" alt="" loading="lazy" decoding="async" />
  <div class="hero-body">
    <div class="section-head">
      <span class="section-head-kicker section-head-kicker-quiet">FIELD NOTES · ISSUE 04</span>
      <span class="section-head-rule"></span>
    </div>
    <h1 class="hero-title">Everything worth building runs out into the fog first.</h1>
    <p class="hero-lede">The photograph is mixed into whatever surface this band is sitting on, at the strength the theme states — so this paragraph reads at the ratio it would have had on a plain section. Switch the theme at the top of the page: the picture has not changed, and what it is mixed into has.</p>
    <div class="cluster hero-actions">
      <a href="#" class="btn btn-primary">READ THE ISSUE</a>
      <a href="#" class="hero-link">Every back issue</a>
    </div>
  </div>
</section>

Four ways to hold the words

Same photograph, four jobs. The default mixes it into the surface everywhere; the other three hand it back its full strength and buy the legibility somewhere else.

SCENE

Mixed into the surface, everywhere. Words go anywhere on it.

SCENE-FOOT

Full strength up top, gone at the foot.

SCENE-LEAD

Full strength beyond the copy, gone behind it.

HTML
<!-- One photograph, four jobs. Only the class on the box changes. -->
<div class="hairline-grid" style="--cell:230px; width:100%">
  <div class="hairline-cell scene" style="min-block-size:210px">
    <img class="scene-media" src="/scenery/facets.webp" alt="" loading="lazy" />
    <span class="section-head-kicker">SCENE</span>
    <p class="placeholder-caption">Mixed into the surface, everywhere. Words go anywhere on it.</p>
  </div>

  <div class="hairline-cell scene scene-foot" style="min-block-size:210px; display:flex; flex-direction:column; justify-content:flex-end">
    <img class="scene-media" src="/scenery/facets.webp" alt="" loading="lazy" />
    <span class="section-head-kicker">SCENE-FOOT</span>
    <p class="placeholder-caption">Full strength up top, gone at the foot.</p>
  </div>

  <div class="hairline-cell scene scene-lead" style="min-block-size:210px">
    <img class="scene-media" src="/scenery/facets.webp" alt="" loading="lazy" />
    <span class="section-head-kicker">SCENE-LEAD</span>
    <p class="placeholder-caption" style="max-inline-size:18ch">Full strength beyond the copy, gone behind it.</p>
  </div>

  <div class="hairline-cell scene scene-clear" style="min-block-size:210px">
    <img class="scene-media" src="/scenery/facets.webp" alt="" loading="lazy" />
  </div>
</div>

It composes, and it owns nothing

A slab is still cream. A card is still a card. A scene decides where a photograph sits and stops there.

ONE SLOT OPEN THIS QUARTER Bring me the part nobody wants to estimate.
BOOK AN INTRO CALL

Thirty minutes, no deck, no obligation.

MOST COMMON Project

No scene at all. This is the card the library has always drawn.

RETAINER A day a week

The same card with a picture behind it, at full strength where nothing is written and gone where these words are.

HTML
<!-- A scene is two classes and an image, and it has no opinion about what it is
     composed onto. The slab keeps every one of its own decisions — it is still
     the cream surface, and the photograph is mixed into the cream. -->
<div class="cta-slab scene" style="width:100%">
  <img class="scene-media" src="/scenery/marbled.webp" alt="" loading="lazy" />
  <div class="cta-slab-body">
    <span class="cta-slab-kicker">ONE SLOT OPEN THIS QUARTER</span>
    <span class="cta-slab-title">Bring me the part nobody wants to estimate.</span>
  </div>
  <div class="cta-slab-action">
    <a href="#" class="btn btn-on-cream">BOOK AN INTRO CALL</a>
    <p class="cta-slab-note">Thirty minutes, no deck, no obligation.</p>
  </div>
</div>

<div class="hairline-grid" style="--cell:280px; width:100%; margin-block-start:32px">
  <div class="hairline-cell offer-card">
    <div class="offer-card-head">
      <span class="offer-card-kicker">MOST COMMON</span>
      <span class="offer-card-title">Project</span>
    </div>
    <p class="offer-card-text">No scene at all. This is the card the library has always drawn.</p>
  </div>
  <!-- A faded variant clears a band and the content has to BE in it, so this
       card pushes itself to the foot. Leave it at the top and the head sits on
       a photograph at full strength, which is the one thing the fade exists to
       prevent. `--scene-clean` is widened here so the band covers all three
       lines rather than cutting through the kicker. -->
  <div class="hairline-cell offer-card scene scene-foot" style="min-block-size:300px; justify-content:flex-end; --scene-clean:58%">
    <img class="scene-media" src="/scenery/curl.webp" alt="" loading="lazy" style="--scene-focus:50% 30%" />
    <div class="offer-card-head">
      <span class="offer-card-kicker">RETAINER</span>
      <span class="offer-card-title">A day a week</span>
    </div>
    <p class="offer-card-text">The same card with a picture behind it, at full strength where nothing is written and gone where these words are.</p>
  </div>
</div>

Reference

Read from primitives/scene.css when this page was built, so it cannot fall behind the stylesheet.

CLASSES.scene.scene-media.scene-clear.scene-foot.scene-lead
SETTINGSSet the first on one element; a theme sets the second for all of them.--scene-strength — falls back to --ds-scene-strength--scene-clean — falls back to --ds-scene-clean--scene-full — falls back to --ds-scene-full
READSNothing from the theme — it is arrangement only.

Notes

WHERE THIS EARNS ITS PLACE, AND WHERE IT DOES NOT

A scene composes onto anything, which is not the same as belonging on everything. The line is easy: a picture behind a box somebody reads is an accent, and a picture behind a box somebody operates is noise the operator has to see past.

REACH FOR ITWHY
heroThe opening statement. The one every client asks for first.
cta-slabThe warm plate that asks for the work. A picture in the cream, and the button unchanged.
shell-flushThe full-bleed band. A scene is more at home here than anywhere else in the library.
fact-stripNumbers over a texture, breaking a page that has been prose for a while.
offer-card, interest-card, feature-cellA card that has to sell something rather than list it.
testimonial, case-plateA quote or a study wants a quiet thing behind it, not beside it.
work-entry, feature-bandA row or a band that is itself the argument, carrying its own subject.
site-footer, articleThe closing block, and a piece's opening band — never the body of one.

Not these, and each for its own reason. site-header, dock, settings-row, process-list, timeline and ledger are dense chrome and data — a reader is scanning them, not looking at them. enquiry-card is full of fields, and a field's border and its error ink both owe a ratio that a photograph will not respect. gallery, triptych, collage and walkthrough are already pictures, and a picture behind pictures is mud.

And not an atom, ever. A frame or a clip already is the picture, an avatar is round and 32px across, and a button with a photograph in it is a button nobody can read.

WHY AN <img> AND NOT A BACKGROUND

Fair question, because background-image is the obvious spelling. It is also the one that cannot be lazy, cannot be found by the browser's preload scanner, cannot carry a srcset, and cannot say it is decorative.

The one that settles it is responsive art direction. Swapping a background by width takes a media query, and this system has none — while an <img> does the whole job with srcset and sizes, which are not breakpoints and ask the browser rather than telling it.

🛑 WHAT THE DEFAULT GUARANTEES, MEASURED

A photograph you have not seen yet is behind somebody's paragraph. That is a contrast problem with no page to look at, so it is answered with arithmetic: composite the two extremes an image can reach — an all-white frame and an all-black one — over all four of the library's surfaces, in both themes, at the shipped --ds-scene-strength.

ROLEWORSTOVER A SCENE
--ds-ink5.85:1Holds AA over any picture
--ds-ink-read4.81:1Holds AA over any picture
--ds-ink-soft3.27:1Does not. Keep it off a scene
--ds-ink-faint2.20:1Does not. Keep it off a scene

So the rule is one sentence: a scene carries ink and ink-read. The two quiet inks cannot be rescued by mixing harder — the strength that would carry ink-faint is about a tenth, and a photograph at a tenth is a smudge. If you want a caption on a picture, that is what scene-foot is for: the band it clears is the surface itself, so the caption reads at its full ratio.

tools/check-theme.mjs holds the first two rows and prints all four, so a retheme cannot walk away from the promise quietly — and cannot leave this table out of date either.

🛑 THE FILM IS THE SURFACE, WHICH IS WHY THERE IS NO VEIL COLOUR

--scene-strength is the picture's opacity, so what it mixes into is whatever is actually painted behind it. Look at the third specimen: the same two classes on a cta slab put the photograph into cream, with no line of CSS anywhere that knows cream exists.

A --ds-scene-veil token would have to name one surface, and would then be visibly the wrong colour on the other three. This way the mix follows the box, for free, in every theme.

THE FADE IS A MASK, NOT A GRADIENT OVER THE TOP

A gradient veil leaves a thinning film of colour over the photograph, so the contrast where the words are still depends on the photograph. A mask removes the picture — the cleared band is the surface itself, at the full ratio the theme states, whatever the image turns out to be.

Between --scene-clean and --scene-full the picture is fading back in. No word belongs in that band.

🛑 A FADED VARIANT CLEARS A BAND, AND YOUR CONTENT HAS TO BE IN IT

This one is easy to miss because it fails quietly. Put scene-foot on a card that lays its content out from the top and the kicker lands on a photograph at full strength — which is the one thing the fade exists to prevent. It happened here while this page was being written, and it was a screenshot that found it, because nothing else can.

So a faded variant is two decisions, not one: pick the side, then put the content on it. The card in the third specimen pushes itself to the foot and widens --scene-clean until the band covers all three lines. If you would rather not think about it, that is exactly what the plain scene is for.

🛑 IT MAKES A STACKING CONTEXT, AND THAT COSTS SOMETHING

The picture sits at z-index: -1, which is what lets the content stay exactly as it was — no wrapper, no positioning of its own. A negative layer escapes to the nearest stacking context though, and without one here the photograph would slide behind the page and vanish, so .scene isolates.

The bill: anything inside a scene that lifts itself with z-index is now trapped in that box and can no longer paint over a later section. A panel that has to escape belongs outside the scene, or in the top layer where a modal already lives.

alt="" — ALWAYS, AND IT IS NOT POLITENESS

A picture behind a headline adds nothing that a reader of the headline has missed. Announcing "photograph of fog on a treeline" before the words is noise with an author's name on it. The media is also pointer-events: none for the same reason: it is scenery, and nothing may pick it up or drag it out of the page.

A picture that is content wants a frame, in the flow, with a real description.

IT PRINTS AS NOTHING, AND HIGH CONTRAST DROPS IT TOO

The same judgement grain makes: a decorative layer that costs ink or costs contrast is a decorative layer that goes. What is left is the section on its own surface, which is exactly the page this library drew before scenes existed.

A KNOB GOES WHERE ITS CLASS GOES

--scene-clean and --scene-full are read inside the scene-foot and scene-lead rules, so they are substituted on the element carrying that class. Put them on the section. --scene-strength and --scene-focus are read on the picture and take either element.

--scene-focus is an object-position, and it is the one setting here with no theme half. Where the subject sits in a photograph is a fact about that photograph — a theme has no opinion about it, so it is written per instance and nowhere else.

WHERE THE PICTURES CAME FROM

The library ships no images at all — the same decision it made about fonts, for the same reason. Everything on this page is the book's own, and Pictures lists all sixteen with the credit each one is owed.