Documents v0.9.0 · previews run the real runtime · experimental features are marked exp

Event Data

concept

event(field) reads data of the current event inside a mutation: where a press happened, which key was pressed, what a field contains. Fields are checked against the trigger at compile time.

On this page · 6 sections+

event(field)

event(field) gives one value from the event that is running the rule: a pointer position, a key, a field’s value. It is valid only inside a mutation of an :on() rule.

pad.cssreactive
.pad {  --x: state(0px);  --y: state(0px);}.pad:on(pointerdown) {  --x: set(event(local-x));  --y: set(event(local-y));}
state()Function · hover any red tokenMakes each matching element the owner of an independent state with an initial value.Reference →
.pad {  --x: state(0px);  --y: state(0px);  --key: state("none");}/* A snapshot of where the press happened, relative to the pad. */.pad:on(pointerdown) {  --x: set(event(local-x));  --y: set(event(local-y));}/* Keyboard fields exist only for keyboard triggers. */.pad:on(keydown) {  --key: set(event(key));}.pad .dot { translate: var(--x) var(--y); }.pad .x { content: var(--x); }.pad .y { content: var(--y); }.pad .k { content: var(--key); }
state()Function · hover any red tokenMakes each matching element the owner of an independent state with an initial value.Reference →
Resultfocusable pad, pointer and keyboard
waiting for interaction
  • A snapshot. The value is copied when the event happens. The state keeps it until the next mutation; nothing follows the pointer afterwards.
  • A closed list. event() reads the fields listed below, nothing else. It is not access to the JavaScript Event object: no methods, no other properties, no script.
  • Checked against the trigger. Each field belongs to a category, and the trigger decides which categories exist. event(key) in an :on(click) rule is a compile error that lists the fields click provides.
  • Only in mutations. Anywhere else, event() is a compile error, because there is no event there.

Reference: event().

Fields

Lengths are in CSS px. A field the event does not carry writes nothing: the mutation is skipped, never set to NaN or an empty value.

General

FieldTypeTriggers
typestringAll. The DOM event type, such as "click"; "drag" for drag phases.

Pointer

FieldTypeTriggers
client-x, client-ypxPointer and mouse events, drag. Viewport coordinates.
page-x, page-ypxPointer and mouse events, drag. Document coordinates.
local-x, local-ypxPointer and mouse events, drag. Relative to the border box of the element the rule matched.
button, buttonsnumberPointer and mouse events, drag. As in MouseEvent.
pointer-id, pressurenumberPointer events and drag. As in PointerEvent.
pointer-typestringPointer events and drag: "mouse", "pen" or "touch".
alt-key, ctrl-key, shift-key, meta-keybooleanPointer, mouse and keyboard events, drag.

Pointer events here are click, contextmenu, pointerdown, pointerup, pointermove, pointerenter, pointerleave, pointercancel, outside(click) and outside(pointerdown). Mouse events are dblclick, mousedown, mouseup, mousemove, mouseenter and mouseleave; they have no pointer-id, pressure or pointer-type. When a browser delivers click as a plain MouseEvent, those three fields write nothing.

map.cssreactive
.map {  --pin-x: state(0px);  --pin-y: state(0px);  --input: state("none");}.map:on(click) {  --pin-x: set(event(local-x));  --pin-y: set(event(local-y));}/* "mouse", "pen" or "touch": style per input type with :when(). */.map:on(pointerdown) {  --input: set(event(pointer-type));}
state()Function · hover any red tokenMakes each matching element the owner of an independent state with an initial value.Reference →

Keyboard

FieldTypeTriggers
key, codestringkeydown, keyup. As in KeyboardEvent.
repeatbooleankeydown, keyup. True while the key auto-repeats.
alt-key, ctrl-key, shift-key, meta-keybooleanAlso available here.
last-key.cssreactive
.field-help {  --last: state("");}.field-help:on(keydown) {  --last: set(event(key));}
state()Function · hover any red tokenMakes each matching element the owner of an independent state with an initial value.Reference →

Form

FieldTypeTriggers
valuestringinput, change. The value of the control the event happened on.
value-as-numbernumberinput, change. Writes nothing when the value is not a number.
checkedbooleaninput, change. For checkboxes and radios.

The control is event.target, and it must be an input, select or textarea; otherwise the field writes nothing. Password, one-time-code and payment fields (autocomplete="cc-…") always give "" for value, and nothing for value-as-number, so a stylesheet can never read what is typed into them.

search.cssreactive
.search {  --query: state("");  --limit: state(10);}.search input[type=search]:on(input) {  --query: set(event(value));}.search input[type=number]:on(change) {  --limit: set(event(value-as-number));}
state()Function · hover any red tokenMakes each matching element the owner of an independent state with an initial value.Reference →

To keep a control and its own state equal in both directions, use state("", bind(value)) instead: see Data Binding.

Drag

Experimental. Available in drag triggers only.

FieldTypeMeaning
x, ylike the stateThe mutated state’s value at drag start, plus the total pointer distance on that axis. The state must hold px or a number.
delta-x, delta-ypxTotal distance since the drag started
movement-x, movement-ypxDistance since the previous drag event
start-x, start-ypxViewport coordinates of the pointerdown

The pointer fields above are available too; local-x and local-y are relative to the element’s box at drag start.

card.cssreactive
.card {  --x: state(0px);  translate: var(--x) 0;  touch-action: none;}.card:on(drag) {  --x: set(event(x));}
state()Function · hover any red tokenMakes each matching element the owner of an independent state with an initial value.Reference →

Scroll

FieldTypeTriggers
scroll-top, scroll-leftpxscroll, scrollend. The scroll offset of the element the rule matched.
feed.cssreactive
.feed {  --top: state(0px);  overflow: auto;}.feed:on(scrollend) {  --top: set(event(scroll-top));}
state()Function · hover any red tokenMakes each matching element the owner of an independent state with an initial value.Reference →

Focus, submit, reset, animation, transition and toggle triggers provide type only.

Elements involved

Three elements can take part in one event:

ElementWhat it isUsed by
event.targetWhere the event happened: possibly a child of the rule’s elementvalue, value-as-number, checked
The rule elementThe element on the event’s path that the :on() rule matchedlocal-x, local-y, scroll-top, scroll-left, element(), attr(), sibling-index()
The state ownerThe nearest element, from the rule element upwards, that declares the mutated stateWhere the value is stored
list.cssreactive
.list {  --picked: state("");}.list li:on(click) {  --picked: set(attr(data-id));}
state()Function · hover any red tokenMakes each matching element the owner of an independent state with an initial value.Reference →

A click on a <span> inside an <li> has the span as event.target. The rule element is the <li>, so attr(data-id) reads the <li>’s attribute, and the value is stored in .list’s --picked.

Snapshots at the event

Inside a mutation, these functions are evaluated once, when the event happens. Outside mutations they keep their usual behavior.

FunctionInside a mutationOutside
mouse(x), mouse(y)The event’s client-x or client-y. mouse(x, local) is event(local-x). Pointer, mouse and drag triggers only.A live value that follows the pointer
element(width), element(height)The rule element’s border-box size at the eventA live value, updated when the element resizes
viewport(width), viewport(height)The window’s inner size in pxNative 100dvw and 100dvh
attr(name, fallback)The rule element’s attribute at the eventIn state(): read once at creation. In other declarations it is native CSS attr(), untouched.
pick(a, b, …), random(min, max, step)A new value at each eventOne value per element, re-rolled only by live() or on()

So event(client-x), mouse(x), element(width) and attr(data-id) answer different questions:

  • event(client-x) is a field of this event, checked against the trigger;
  • mouse(x) in a mutation is the same number. Outside a mutation it is a subscription to the pointer, re-evaluated as it moves;
  • element(width) measures the rule element, not the event;
  • attr(data-id) reads the rule element’s markup, whatever the event was.
dice.cssreactive
.dice {  --roll: state(1);}/* A new number at each click. random(min, max, step) and by step both work here. */.dice:on(click) {  --roll: set(random(1, 6, 1));}
state()Function · hover any red tokenMakes each matching element the owner of an independent state with an initial value.Reference →

Stability

The pointer, keyboard and form fields are recommended as stable for 0.9.0. The drag fields are experimental, like drag gestures, until they are validated on real touch and pen hardware.

Experimental · syntax may change between minor versions