Skip to content

Getting Started

Terminal window
npm i prop-for-that

Import prop-for-that/auto and it wires everything for you — declaratively, with nothing attached unless the DOM asks for it:

  • Scans the DOM for [data-props-for] attributes and binds the named sources to those elements. Globals are declared too — put them on the root <html> and they write to :root.
  • Loads plugin sources on demand. The first time a data-props-for key needs a plugin, its chunk is dynamically imported and registered, then the binding attaches — no registerPlugins(), no separate plugins import.
  • Keeps everything in sync with a single MutationObserver: elements added later are bound, removed elements are torn down and their properties cleaned up, and editing an element’s data-props-for value re-syncs just the keys that changed — so you can add or drop a source at runtime by changing the attribute alone.

Because plugins lazy-load via dynamic import(), load auto as a module script (the bare <script src> drop-in is gone):

<!-- from a CDN that serves the dist tree verbatim (unpkg / jsDelivr file paths) -->
<script type="module" src="https://unpkg.com/prop-for-that/dist/auto.js"></script>
<!-- or, with a bundler -->
<script type="module">import 'prop-for-that/auto'</script>
<html data-props-for="viewport pointer"> <!-- globals → :root -->
<input type="range" min="0" max="100" data-props-for="range">
<section data-props-for="size visibility"></section>
input {
background: hsl(calc(var(--live-value-pct) * 120) 80% 50%);
}
section {
opacity: var(--const-has-entered);
transition: opacity 0.4s;
}

Want the values to interpolate? Add data-props-typed to the root <html> and every --live-* this page writes is registered as an @property — the markup equivalent of configure({ typed: true }):

<html data-props-typed></html>

Import individual functions for explicit control over which sources are active and when they’re torn down:

import { propsFor, configure } from 'prop-for-that'
// write viewport to :root (pointer is now an opt-in plugin — see Plugins)
propsFor(['viewport'])
// write the range source to a specific element; returns a disposer.
// an element's id is a ready-made global in JS — no query selector needed.
// here, <input id="slider" type="range" min="0" max="100">
const dispose = propsFor(slider, ['range'])
// later, tear it down cleanly
dispose()

Use configure() to change the property prefixes or the global root target, before attaching any sources:

import { configure } from 'prop-for-that'
configure({ livePrefix: '--pft-', constPrefix: '--pft-const-' })

A few values are read once and matter for the first paint: scrollbar width, device pixel ratio, CPU cores. Load the head entry as a synchronous inline script so the properties exist before any CSS applies:

<head>
<script type="module">import 'prop-for-that/head'</script>
<!-- sets --const-scrollbar-w, --const-scrollbar-thin-w, --const-dpr, --const-cores, --const-mem -->
</head>

These use --const-* names and are never overwritten after that first write.