style.ref(label?) creates a ref: a name for an element that other styles can
refer to. Attach the ref to an element with style(ref). Then use its methods to
style other elements from that element’s state, size, or position.
Example
Source
import { style } from "stillwind/react";
const card = style.ref("card");
export const container = style(card, card.asContainer("inline-size"));
export const child = style({
[card("hover")]: "text-blue-600",
[card.at("width >= 40rem")]: "grid-cols-2",
});Compiled code
const card = undefined;
export const container = {className:"sw_28iqw sw_card_uryy0"};
export const child = {className:"sw_6hxbo"};Generated CSS
.sw_28iqw:where(.sw_card_uryy0) {
container-name: sw-c-card-uryy0;
container-type: inline-size;
}
@container sw-c-card-uryy0 (width >= 40rem) {
.sw_6hxbo {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
}
@media (hover: hover) {
.sw_6hxbo:is(:where(.sw_card_uryy0):hover *) {
color: var(--color-blue-600);
}
}Declare a ref
Write style.ref() as the initial value of a variable: const card = style.ref("card").
The declaration can be at the top level of a module, in a function, or in a
callback such as the one that you pass to map().
items.map((item) => {
const row = style.ref("row");
return (
<li {...style(row, "p-4")}>
<span {...style({ [row("hover")]: "underline" })}>{item}</span>
</li>
);
});The compiler generates a unique name for each style.ref() call in the source.
The name stays the same in every render, loop iteration, and function call. You
can export a ref, import it, and pass it as an argument.
The argument of style.ref(), such as "row" in style.ref("row"), is a
label. The label only makes the generated names easier to read, such as in the
browser’s developer tools. It does not make the name unique, and you can omit
it: const row = style.ref(). Two refs with the same label stay separate, and
so do two refs without a label. When you write a label, it must be a string
literal.
Because the name stays the same, a ref cannot distinguish nested elements that
use the same declaration. For example, a tree node can render its child nodes
inside its ref element. Every level then has the same name, and
node("hover") matches while any ancestor node is hovered, not only the
nearest one.
Methods
| Method | Where to write it | Effect |
|---|---|---|
ref |
A style() argument |
Attaches the ref to the element |
ref() |
A computed key in style() |
Matches inside the ref element, optionally in a state |
ref().in() |
After a ref condition | Matches inside a shared ancestor, such as for siblings |
ref.at() |
A computed key in style() |
Matches a container query on the ref element |
ref.asContainer() |
A style() argument |
Makes the ref element a named container |
ref.asAnchor() |
A style() argument |
Makes the ref element a named anchor |
ref.positionAnchor() |
A style() argument |
Positions the styled element against the anchor |
Write each method call directly in style(). You cannot store the result of a
method call in a variable and use it later.
Generated code
When the compiler knows which ref a call uses, the ref becomes plain class names
and selectors, and the ref variable can become undefined in JavaScript. When a
call chooses among several refs at runtime, the generated code keeps the fields
that the choice needs. The compiled code reads those fields directly. In
development, Stillwind checks them first. The code does not watch the DOM.
See Element relationships for task-based examples.