# property

Emit an `@property` rule that registers a custom property with a syntax, inheritance, and initial value.

`property` registers an authored custom-property name. Registration changes how the browser computes, inherits, and animates the value. For a typed variable with a generated name and typed assignments, use [`variable`](/docs/api/core/variable).

```ts title="src/properties.ts"
import { property } from 'zyzz/web'

// Emits `@property --angle{syntax:"<angle>";inherits:false;initial-value:0deg;}`
property({
  inherits: false,
  initialValue: '0deg',
  name: '--angle',
  syntax: '<angle>',
})
```

## Signature

```ts
// One registration, optionally inside grouping keys
property(options)
```

## Parameters

### options.name

* **Type:** `` `--${string}` ``

The registered custom-property name, emitted as authored. Styles read it with `var()` and assign it as an ordinary custom property.

```ts
// Styles read the value with `var(--angle)`
property({
  inherits: false,
  initialValue: '0deg',
  name: '--angle',
  syntax: '<angle>',
})
```

### options.syntax

* **Type:** `string`

A syntax descriptor: one component type such as `<length>`, alternatives joined with `|`, `+` or `#` multipliers, or the universal `*`.

```ts
import { property } from 'zyzz/web'

property({
  inherits: false,
  // One or more lengths, or the keyword `auto`
  initialValue: '4px 8px',
  syntax: '<length>+ | auto',
  name: '--spacing',
})
```

### options.inherits

* **Type:** `boolean`

Whether elements inherit the value from their parent.

```ts
// Descendants inherit the assigned color
property({
  inherits: true,
  initialValue: 'black',
  name: '--ink',
  syntax: '<color>',
})
```

### options.initialValue

* **Type:** `string | number`
* **Default:** `undefined`

The initial value, which must match the syntax and be computationally independent, so `1em` is rejected. Every syntax except `*` requires it.

```ts
import { property } from 'zyzz/web'

// The universal syntax needs no initial value
property({ inherits: true, name: '--payload', syntax: '*' })
```

### options\[atRule]

* **Type:** `` '@layer' | `@${'container' | 'layer' | 'media' | 'supports'}${' ' | '\t' | '\n' | '\r' | '\f' | '(' | `/*${string}*/`}${string}` ``

Grouping keys around a complete registration. Each value holds a complete definition or further grouping keys, and outer keys emit outer groups. A bare `@layer` key emits an anonymous layer.

```ts
import { property } from 'zyzz/web'

property({
  // Emits the registration inside `@layer defaults`
  '@layer defaults': {
    inherits: false,
    initialValue: '0px',
    name: '--gap',
    syntax: '<length>',
  },
})
```

## Returns

`void`. The compiler erases the call and keeps the registration in the shared stylesheet. Vite, Unplugin, and `zyzz/node` scan the source tree, so unimported modules still contribute. Next.js compiles only imported modules, so import the declaring module from an entrypoint there.

## Types

* **`property.Options`:** The accepted registration.

```ts
import type { property } from 'zyzz/web'

// Reads the accepted name shape
type Name = property.Options['name']
```

## Errors

TypeScript rejects unknown options, invalid syntax descriptors, and a missing initial value.

```ts
import { property } from 'zyzz/web'

// `<length>` requires an initial value
property({ inherits: false, name: '--gap', syntax: '<length>' })
// error: Argument of type '{ inherits: false; name: "--gap"; syntax: "<length>"; }' is not assignable to parameter of type '{ readonly inherits: false; readonly name: "--gap"; readonly syntax: "<length>"; } & NoInfer<Accepted<{ readonly inherits: false; readonly name: "--gap"; readonly syntax: "<length>"; }>>'.
// Type '{ inherits: false; name: "--gap"; syntax: "<length>"; }' is not assignable to type 'Accepted<{ readonly inherits: false; readonly name: "--gap"; readonly syntax: "<length>"; }>'.
// Property 'initialValue' is missing in type '{ inherits: false; name: "--gap"; syntax: "<length>"; }' but required in type '{ readonly initialValue: string | number; }'.
```

The compiler reports `Source.ExtractError` for an initial value that does not match the syntax or depends on other values. Native builds reject the call with `Native.CompileError`.
