keyframes and positionTrykeyframes() and positionTry() define an at-rule next to the styles that use it and return its name, a typed value that fits where the grammar wants a name.
import { const animation: Prop<"animation">`<single-animation>#`. Chrome 43, Edge 12, Firefox 16, Safari 9, iOS 9, Android 43. [MDN](https://developer.mozilla.org/docs/Web/CSS/animation)animation, const cn: (...styles: Style[]) => Stylecn, const hover: StateWrapChrome 1, Edge 12, Firefox 1, Safari 2, iOS 1, Android 18. [MDN](https://developer.mozilla.org/docs/Web/CSS/:hover)hover, const keyframes: (steps: Steps) => Keyframes`keyframes({ from: opacity(0), to: opacity(1) })`: a `@keyframes` rule named by a hash of its content, in the sheet of
the modules that use the name. Each step is checked like a class; no conditions.keyframes, const margin: Prop<"margin">`<'margin-top'>{1,4}`. Chrome 1, Edge 12, Firefox 1, Safari 1, iOS 1, Android 18. [MDN](https://developer.mozilla.org/docs/Web/CSS/margin)margin, const opacity: Prop<"opacity">`<opacity-value>`. Chrome 1, Edge 12, Firefox 1, Safari 2, iOS 1, Android 18. [MDN](https://developer.mozilla.org/docs/Web/CSS/opacity)opacity, const positionTry: ((style: Style) => PositionTry) & Prop<"position-try", Style>`positionTry(cn(top("anchor(bottom)"), margin(2)))`: a `@position-try` rule, in the sheet of the modules that use its
name. Only inset, margin, sizing, self-alignment, `position-anchor` and `position-area` are allowed (a build error).
`position-try` is also a property: with value parts (`positionTry("flip-block")`) it is that shorthand, as before.positionTry, const positionTryFallbacks: Prop<"position-try-fallbacks">`none | [ [<dashed-ident> || <try-tactic>] | <position-area> ]#`. Chrome 128, Edge 128, Firefox 147, Safari 26, iOS 26, Android 128. [MDN](https://developer.mozilla.org/docs/Web/CSS/position-try-fallbacks)positionTryFallbacks, const top: Prop<"top">`auto | <length-percentage> | <anchor()> | <anchor-size()>`. Chrome 1, Edge 12, Firefox 1, Safari 1, iOS 1, Android 18. [MDN](https://developer.mozilla.org/docs/Web/CSS/top)top, const transform: Prop<"transform">`none | <transform-list>`. Chrome 36, Edge 12, Firefox 16, Safari 9, iOS 9, Android 36. [MDN](https://developer.mozilla.org/docs/Web/CSS/transform)transform } from "cssints" with { type: "cssints" };
export const const fade: Keyframesfade = function keyframes(steps: Steps): Keyframes`keyframes({ from: opacity(0), to: opacity(1) })`: a `@keyframes` rule named by a hash of its content, in the sheet of
the modules that use the name. Each step is checked like a class; no conditions.keyframes({ Steps.from?: Style | undefinedfrom: opacity<readonly [0]>(parts_0: 0): Style`<opacity-value>`. Chrome 1, Edge 12, Firefox 1, Safari 2, iOS 1, Android 18. [MDN](https://developer.mozilla.org/docs/Web/CSS/opacity)opacity(0), Steps.to?: Style | undefinedto: opacity<readonly [1]>(parts_0: 1): Style`<opacity-value>`. Chrome 1, Edge 12, Firefox 1, Safari 2, iOS 1, Android 18. [MDN](https://developer.mozilla.org/docs/Web/CSS/opacity)opacity(1) });
export const const wiggle: Keyframeswiggle = function keyframes(steps: Steps): Keyframes`keyframes({ from: opacity(0), to: opacity(1) })`: a `@keyframes` rule named by a hash of its content, in the sheet of
the modules that use the name. Each step is checked like a class; no conditions.keyframes({ Steps.from?: Style | undefinedfrom: transform<readonly ["rotate(0deg)"]>(parts_0: "rotate(0deg)"): Style`none | <transform-list>`. Chrome 36, Edge 12, Firefox 16, Safari 9, iOS 9, Android 36. [MDN](https://developer.mozilla.org/docs/Web/CSS/transform)transform("rotate(0deg)"), "50%": function cn(...styles: Style[]): Stylecn(transform<readonly ["rotate(8deg)"]>(parts_0: "rotate(8deg)"): Style`none | <transform-list>`. Chrome 36, Edge 12, Firefox 16, Safari 9, iOS 9, Android 36. [MDN](https://developer.mozilla.org/docs/Web/CSS/transform)transform("rotate(8deg)"), opacity<readonly [0.5]>(parts_0: 0.5): Style`<opacity-value>`. Chrome 1, Edge 12, Firefox 1, Safari 2, iOS 1, Android 18. [MDN](https://developer.mozilla.org/docs/Web/CSS/opacity)opacity(0.5)), Steps.to?: Style | undefinedto: transform<readonly ["rotate(0deg)"]>(parts_0: "rotate(0deg)"): Style`none | <transform-list>`. Chrome 36, Edge 12, Firefox 16, Safari 9, iOS 9, Android 36. [MDN](https://developer.mozilla.org/docs/Web/CSS/transform)transform("rotate(0deg)") });
export const const above: PositionTryabove = function positionTry(style: Style): PositionTry (+1 overload)`positionTry(cn(top("anchor(bottom)"), margin(2)))`: a `@position-try` rule, in the sheet of the modules that use its
name. Only inset, margin, sizing, self-alignment, `position-anchor` and `position-area` are allowed (a build error).
`position-try` is also a property: with value parts (`positionTry("flip-block")`) it is that shorthand, as before.positionTry(function cn(...styles: Style[]): Stylecn(top<readonly ["anchor(bottom)"]>(parts_0: "anchor(bottom)"): Style`auto | <length-percentage> | <anchor()> | <anchor-size()>`. Chrome 1, Edge 12, Firefox 1, Safari 1, iOS 1, Android 18. [MDN](https://developer.mozilla.org/docs/Web/CSS/top)top("anchor(bottom)"), margin<readonly [2]>(parts_0: 2): Style`<'margin-top'>{1,4}`. Chrome 1, Edge 12, Firefox 1, Safari 1, iOS 1, Android 18. [MDN](https://developer.mozilla.org/docs/Web/CSS/margin)margin(2)));
export const const a: Stylea = animation<readonly [Keyframes, "200ms", "ease-out"]>(parts_0: Keyframes, parts_1: "200ms", parts_2: "ease-out"): Style`<single-animation>#`. Chrome 43, Edge 12, Firefox 16, Safari 9, iOS 9, Android 43. [MDN](https://developer.mozilla.org/docs/Web/CSS/animation)animation(const fade: Keyframesfade, "200ms", "ease-out");
export const const b: Styleb = function hover(...styles: Style[]): StyleChrome 1, Edge 12, Firefox 1, Safari 2, iOS 1, Android 18. [MDN](https://developer.mozilla.org/docs/Web/CSS/:hover)hover(animation<readonly [Keyframes, "1s", "infinite"]>(parts_0: Keyframes, parts_1: "1s", parts_2: "infinite"): Style`<single-animation>#`. Chrome 43, Edge 12, Firefox 16, Safari 9, iOS 9, Android 43. [MDN](https://developer.mozilla.org/docs/Web/CSS/animation)animation(const wiggle: Keyframeswiggle, "1s", "infinite"));
export const const c: Stylec = positionTryFallbacks<readonly [PositionTry, "flip-inline"]>(parts_0: PositionTry, parts_1: "flip-inline"): Style`none | [ [<dashed-ident> || <try-tactic>] | <position-area> ]#`. Chrome 128, Edge 128, Firefox 147, Safari 26, iOS 26, Android 128. [MDN](https://developer.mozilla.org/docs/Web/CSS/position-try-fallbacks)positionTryFallbacks(const above: PositionTryabove, "flip-inline");
export const const d: Keyframesd = function keyframes(steps: Steps): Keyframes`keyframes({ from: opacity(0), to: opacity(1) })`: a `@keyframes` rule named by a hash of its content, in the sheet of
the modules that use the name. Each step is checked like a class; no conditions.keyframes({ Steps.from?: Style | undefinedfrom: opacity<readonly ["lots"]>(parts_0: "opacity: unexpected \"lots\" in \"lots\", grammar <opacity-value>"): Style`<opacity-value>`. Chrome 1, Edge 12, Firefox 1, Safari 2, iOS 1, Android 18. [MDN](https://developer.mozilla.org/docs/Web/CSS/opacity)opacity("lots") }); // error: opacity: unexpected "lots"export const const e: Keyframese = function keyframes(steps: Steps): Keyframes`keyframes({ from: opacity(0), to: opacity(1) })`: a `@keyframes` rule named by a hash of its content, in the sheet of
the modules that use the name. Each step is checked like a class; no conditions.keyframes({ halfway: opacity<readonly [0]>(parts_0: 0): Style`<opacity-value>`. Chrome 1, Edge 12, Firefox 1, Safari 2, iOS 1, Android 18. [MDN](https://developer.mozilla.org/docs/Web/CSS/opacity)opacity(0) }); // error: a step is from, to or a percentageexport const const f: Stylef = positionTryFallbacks<readonly [Keyframes]>(parts_0: "position-try-fallbacks: unexpected \"⟨custom-ident⟩\" in \"⟨custom-ident⟩\", grammar none | [ [<dashed-ident> || <try-tactic~w>] | <position-area~w> ]#"): Style`none | [ [<dashed-ident> || <try-tactic>] | <position-area> ]#`. Chrome 128, Edge 128, Firefox 147, Safari 26, iOS 26, Android 128. [MDN](https://developer.mozilla.org/docs/Web/CSS/position-try-fallbacks)positionTryFallbacks(fade); // error: a keyframes name is not a dashed identkeyframes() and the argument of positionTry() are made of member calls (opacity(0), cn(...)), as cn() and cv() take them: they are checked by the grammar of each property, at the member call in the types and at the call of keyframes() at build time, with the support warnings of a class. A step is from, to or one percentage ("50%", 0 to 100); a list ("0%, 100%") is not supported. A condition, a firstThatWorks() or a member with a marker class (a plugin's) inside a step is a build error, since an at-rule step has none.positionTry() takes what @position-try takes: inset, margin and sizing properties, align-self, justify-self, place-self, position-anchor and position-area (CSS Anchor Positioning §6.4). Any other property (positionTry(cn(padding(2)))) is a build error at the call; the types cannot see which property a style holds. position-try is a property as well, so with value parts positionTry("flip-block") is still that shorthand; one style is the rule.kf-1a2b3c4d for keyframes, --pt-1a2b3c4d for @position-try, so two blocks with the same steps are one name and one rule, from any module. It is a Typed OM value: CSSStyleValue<"custom-ident"> for keyframes (animation, animationName), <dashed-ident> for positionTry() (positionTryFallbacks); it fits nowhere else. A keyframes() in a client module ships as its name string.animation(fade, ...), inside cn(), a condition, a cv() or a plugin's kernel written as styles) puts the rule in the sheet of its module, once however many use it. A rule that nothing uses is in no sheet, so there is nothing to shake: a module that imports a helper but does not use a name has no rule. It is a kernel (see "Plugins"), keyed by the content, in layer _.k, with requires set to css.at-rules.keyframes or css.at-rules.position-try: a target that lacks it gets a support warning, never an error.@keyframes). Names are hashes of the content, so no two rules of different content share one and the order never decides; the rules go in _.k, below every class layer, and the layer statement stays as it is.export const fade = keyframes(...) in a module imported with the attribute (like a token) is a definition site: it ships nothing, and the components that import it and use it carry the rule.firstThatWorks() or style() (an inline style has no sheet): both reject it with a message. A value of custom-ident kind is accepted by the grammar as a keyframes name whichever way it was made, so a typo in a hand-written animationName("fadee") is not caught.@layer _.k {
@keyframes kf-0e6af964{from{opacity:0}to{opacity:1}}
@position-try --pt-23965b44{top:anchor(bottom);margin:0.5rem}
}
@layer _.a {
._44ecsn{animation:kf-0e6af964 200ms ease-out}
}