Skip to content

style.ref() and ref methods

Name an element with a ref, and style other elements from its state, size, or anchor position.

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.