> ## Documentation Index
> Fetch the complete documentation index at: https://docs.tipar.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Text & styling

> The text and richText nodes, the style object, colours, and alignment.

## text

A single styled string. The most common node by far.

```json theme={"dark"}
{
  "type": "text",
  "value": "Invoice {{invoice.number}}",
  "style": { "fontSize": 18, "bold": true },
  "align": "right"
}
```

| Field   | Type                              | Required | Notes                                                                        |
| ------- | --------------------------------- | -------- | ---------------------------------------------------------------------------- |
| `value` | string                            | **yes**  | The text. Supports [`{{interpolation}}`](/templates/overview#interpolation). |
| `style` | [Style](#style)                   | no       | Typography for this string. Merged over `page.defaultTextStyle`.             |
| `align` | `"left"` · `"center"` · `"right"` | no       | Default `left`.                                                              |

A `text` value can mix literal text and tokens freely: `"Total due: {{invoice.total}}"`.

## style

The style object controls typography. Every field is optional; a node's `style` merges over the page's `defaultTextStyle`.

```json theme={"dark"}
{
  "fontSize": 10,
  "bold": true,
  "semiBold": false,
  "italic": false,
  "color": "#0f1714"
}
```

| Field      | Type              | Notes                                    |
| ---------- | ----------------- | ---------------------------------------- |
| `fontSize` | number (points)   | Must be greater than 0 when set.         |
| `bold`     | boolean           | Heavy weight.                            |
| `semiBold` | boolean           | Medium weight, between regular and bold. |
| `italic`   | boolean           | Italic slant.                            |
| `color`    | [Color](#colours) | Text colour.                             |

<Warning>
  Only `fontSize` and `color` inherit from `page.defaultTextStyle`. `bold`, `semiBold`, and `italic` take effect **only** on the node where you set them — so a page default never silently bolds everything. Set the weight on each node that needs it.
</Warning>

## Colours

A colour is **either** a hex string **or** a named palette token.

<Tabs>
  <Tab title="Hex">
    `#RGB`, `#RRGGBB`, or `#RRGGBBAA` (3, 6, or 8 hex digits; case-insensitive). The 8-digit form includes alpha.

    ```json theme={"dark"}
    { "color": "#0a9d5f" }
    { "color": "#666" }
    { "color": "#0a9d5f80" }
    ```
  </Tab>

  <Tab title="Palette token">
    A dotted token from QuestPDF's built-in Material palette: a colour name and a shade. Case-insensitive.

    ```json theme={"dark"}
    { "color": "grey.darken1" }
    { "color": "blue.medium" }
    { "color": "red.lighten2" }
    { "color": "indigo.darken3" }
    ```

    Names follow `‹colour›.‹shade›`, where shade is `lighten5`…`lighten1`, `medium`, `darken1`…`darken4` (and `accent1`…`accent4` for colours that have them). An unknown token is rejected at validation time with `422`. See the [full schema](/api-reference/template-schema#colours) and the [QuestPDF colour reference](https://www.questpdf.com/api-reference/colors.html).
  </Tab>
</Tabs>

<Tip>
  For brand colours, use hex. For quick, harmonious greys and accents on internal documents, the palette tokens save you picking values — `grey.darken1` for muted labels, `grey.lighten2` for hairline borders are common choices.
</Tip>

## richText

When one line needs **more than one style**, or a dynamic **page number**, use `richText` instead of `text`. It's a sequence of spans laid out inline.

```json theme={"dark"}
{
  "type": "richText",
  "align": "center",
  "spans": [
    { "value": "Page ", "style": { "fontSize": 9, "color": "grey.darken1" } },
    { "pageNumber": true },
    { "value": " of ", "style": { "fontSize": 9, "color": "grey.darken1" } },
    { "totalPages": true }
  ]
}
```

| Field   | Type                              | Required | Notes                                        |
| ------- | --------------------------------- | -------- | -------------------------------------------- |
| `spans` | Span\[]                           | **yes**  | One or more spans, rendered inline in order. |
| `align` | `"left"` · `"center"` · `"right"` | no       | Default `left`.                              |

A **span** is one of three shapes:

| Span        | Shape                              | Renders                                   |
| ----------- | ---------------------------------- | ----------------------------------------- |
| Text run    | `{ "value": "…", "style": { … } }` | Interpolatable, individually styled text. |
| Page number | `{ "pageNumber": true }`           | The current page number.                  |
| Total pages | `{ "totalPages": true }`           | The total page count.                     |

<Note>
  `pageNumber` and `totalPages` are the **only** way to print page numbers, and they only make sense in a `footer` or `header` (which repeat on every page). In the body they'd render once. See [Headers & footers](/templates/headers-footers).
</Note>

<Card title="Next: Tables" icon="table-cells" href="/templates/tables">
  Repeat rows over an array in your data.
</Card>
