---
title: "Style declarations — API reference"
description: "The closed, target-neutral style vocabulary a quario definition draws from, with the box, format and currency declarations."
url: "https://getquario.com/docs/reference/style-declarations"
---

# Style declarations

One closed vocabulary, target-neutral. Each render target maps it to its own
model. An unknown name is a definition error. Every value may be a literal or
an `=` expression.

## `StyleDeclarations`

| Declaration | Value | Meaning |
| --- | --- | --- |
| `family` | `"sans"`, `"serif"`, `"mono"`, or an embedded family name | typeface family |
| `size` | number | font size in points |
| `bold` | boolean | weight |
| `italic` | boolean | slant |
| `underline` | boolean | underline decoration |
| `strikethrough` | boolean | strikethrough decoration |
| `uppercase` | boolean | draw the text in capitals |
| `color` | `#rgb` or `#rrggbb` | text colour, hex only |
| `background` | `#rgb` or `#rrggbb` | background colour, hex only |
| `align` | `"left"`, `"center"`, `"right"` | horizontal alignment in the cell |
| `valign` | `"top"`, `"middle"`, `"bottom"` | vertical alignment in a box taller than its content |
| `format` | a kind, or `{ kind, digits, negative, zero }` / `{ kind, form }` | how a number or date presents |
| `currency` | ISO 4217 code | the denomination of a `currency` cell |
| `href` | a URL, or `#` and a group’s `label` | where the text points |
| `spaceBefore` / `spaceAfter` | number >= 0 | blank space before or after a band item, in points |

Plus the box below.

`valign` is legal only where a box has height it didn’t ask for, which means
table cells and split slots. On a stacked text item, a band image, or the
report default it’s a definition error.

## `BoxDeclarations`

Padding and border, per side. `<Side>` is `Top`, `Right`, `Bottom` or `Left`.

| Declaration | Value | Meaning |
| --- | --- | --- |
| `padding<Side>` | number >= 0 | inset in points on that side |
| `border<Side>Width` | number >= 0 | stroke width in points, `0` draws nothing |
| `border<Side>Style` | `"solid"`, `"dashed"`, `"dotted"` | line style of that side |
| `border<Side>Color` | `#rgb` or `#rrggbb` | stroke colour of that side |

Border-box, no collapse. A border side is width, style and colour together, or
none. An incomplete literal is a definition error, while an incomplete
expression result contributes nothing at render.

## `FormatDeclaration`

```ts title="signature"
type FormatKind = 'number' | 'currency' | 'percent' | 'date'
type DateForm = 'short' | 'medium' | 'long' | 'full'

type NegativeReading = 'minus' | 'parens'
type ZeroReading = 'number' | 'dash'

type FormatDeclaration =
  | FormatKind
  | {
      kind: 'number' | 'currency' | 'percent'
      digits?: number
      negative?: NegativeReading
      zero?: ZeroReading
    }
  | { kind: 'date'; form?: DateForm }
```

`digits` is a whole number from 0 to 20. `negative` chooses `-1,204.00` or
`(1,204.00)`, and `zero` chooses `0.00` or `-`. Both default to the first, so
no existing definition moves, and `date` takes neither. A modifier a kind
doesn’t understand is a definition error. Only the whole declaration may be an
expression, never a modifier inside it.

`format` and `currency` are legal wherever a node has a cell value, which means
text items, column cells, headers, and total cells. Both are definition errors
on an image, on a row’s `style`, and on the report default. Both are legal on a
styled run, which carries the inline half of the vocabulary.

## `ResolvedFormat`

```ts title="signature"
type ResolvedFormat =
  | {
      kind: 'number' | 'currency' | 'percent'
      digits?: number
      negative: NegativeReading
      zero: ZeroReading
    }
  | { kind: 'date'; form: DateForm }
```

What crosses the event stream. Never the author’s shorthand, always the object
with the answer filled in.

## Narrowed sets

```ts title="signature"
type ReportStyleDeclarations = Pick<StyleDeclarations, 'family' | 'size'>

type ImageStyleDeclarations = Pick<
  StyleDeclarations,
  'background' | 'align' | 'spaceBefore' | 'spaceAfter' | keyof BoxDeclarations
>

type StackedStyleDeclarations = Omit<StyleDeclarations, 'valign'>

type CellStyleDeclarations = Omit<StyleDeclarations, 'spaceBefore' | 'spaceAfter'>

type RowStyleDeclarations = Omit<
  StyleDeclarations,
  'format' | 'currency' | 'href' | 'spaceBefore' | 'spaceAfter'
>

type SlotStyleDeclarations = Omit<StyleDeclarations, 'spaceBefore' | 'spaceAfter'>

type RunStyleDeclarations = Pick<
  StyleDeclarations,
  | 'family' | 'size' | 'bold' | 'italic' | 'underline' | 'strikethrough'
  | 'color' | 'background' | 'uppercase' | 'format' | 'currency' | 'href'
>
```

Each set states a narrowing the engine has always applied, so a node’s `style`
type refuses what a render would have refused. The report default carries
`family` and `size` only, and an image carries no text declarations. A stacked
item drops `valign`: its box is its own height, so there is nothing to align
against. A slot’s box is the split’s height, which is why a slot keeps the
name. A table cell and a split slot drop flow spacing, which describes a band
item rather than a cell. A row box drops that too, and with it the three names
that present a value. A box wraps cells and holds none of its own, so `format`,
`currency` and `href` have nothing to act on. A styled run carries the inline
half. The box and flow spacing describe a block, and `align` describes a line.
Any of them on a run is a definition error naming the run.

## Layering

Five layers, outermost in: the target’s own baseline, the report default, then
the band-role default a target supplies for headline roles. Then the node’s own
`style`, and last a styled run’s. A split’s `style` is a node’s own for every
slot under it, so it outranks the band-role default. The report header’s
band-role size is a factor over the document’s, 1.4×, so a document declaring
`size: 20` renders its headline at 28.

`format` layers whole. A cell that names it restates the entire declaration.

## `STYLE_NAMES`

```ts title="signature"
const STYLE_NAMES: readonly string[]
const RUN_STYLE_NAMES: readonly string[]
const REPORT_STYLE_NAMES: readonly string[]
function isBoxName(name: string): boolean
```

The vocabulary as data, in the order this page lists it. Import it rather than
keeping a copy. `RUN_STYLE_NAMES` is the run’s subset, in the same order, and
`REPORT_STYLE_NAMES` is the report default’s two names. `isBoxName` answers
whether a name is part of the box, a padding or a border side. That’s the
partition that defines a table row’s box. A target that removes the box from a
style asks it rather than matching the two prefixes itself.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https://getquario.com/"},{"@type":"ListItem","position":2,"name":"Docs","item":"https://getquario.com/docs"},{"@type":"ListItem","position":3,"name":"Style declarations","item":"https://getquario.com/docs/reference/style-declarations"}]}
```
