> For the complete documentation index, see [llms.txt](https://docs.rowsncolumns.app/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.rowsncolumns.app/configuration/features/gradient-fills.md).

# Gradient cell fills

Set a gradient on any cell's `uf` (user-entered format) and the canvas renderer paints it directly. Supports both **linear** (with a rotation angle) and **path / radial** (with axis-of-radial insets), each with two or more color stops.

Mirrors OOXML's `<gradientFill>` element. XLSX round-trip is full; the canvas paint uses native `CanvasGradient` (`createLinearGradient` / `createRadialGradient`).

## Authoring

```ts
const cellData: CellData = {
  ue: { sv: "Header" },
  fv: "Header",
  uf: {
    gradient: {
      type: "linear",
      degree: 90,              // 0 = left→right, 90 = top→bottom, 180 = right→left, 270 = bottom→top
      stops: [
        { position: 0, color: "#fde68a" },
        { position: 1, color: "#dc2626" },
      ],
    },
  },
};
```

`position` is on `[0, 1]`. At least two stops are required; three+ stops give multi-stop ramps.

## Path / radial gradients

Use `type: "path"` with four optional inset values describing where the inner stop's "core" rectangle sits relative to the cell:

```ts
uf: {
  gradient: {
    type: "path",
    left: 0.5,
    right: 0.5,
    top: 0.5,
    bottom: 0.5,
    stops: [
      { position: 0, color: "#ffffff" },   // center
      { position: 1, color: "#7c3aed" },   // edges
    ],
  },
}
```

The example above produces a radial gradient centered in the cell. Shift the center off-axis by adjusting `left` / `right` / `top` / `bottom` (each 0..1 — the inset of the inner stop's core from that edge).

## Three-stop ramps

```ts
uf: {
  gradient: {
    type: "linear",
    degree: 45,
    stops: [
      { position: 0,   color: "#fef08a" },   // yellow at one end
      { position: 0.5, color: "#22c55e" },   // green in the middle
      { position: 1,   color: "#1e40af" },   // blue at the other end
    ],
  },
}
```

## Precedence over solid + pattern fills

When `gradient` is present on a cell's format, it takes precedence over `backgroundColor` and `fillPattern`. Excel's UI treats fills as mutually exclusive on a single cell, so the renderer matches that: pattern + solid are ignored.

The `cellXfsRegistry` deduplication hash includes the gradient stops, so two cells with the same gradient share a `sid` reference (same compression behavior as for regular fills).

## XLSX round-trip

Parser reads `<gradientFill>` from `xl/styles.xml` and hydrates the `gradient` field on `CellFormat`. Exporter emits the same element with `<stop position><color rgb="..."/></stop>` children. Both linear and path/radial round-trip. The OOXML attributes map 1:1 onto the type's fields:

| OOXML                                   | Field                             |
| --------------------------------------- | --------------------------------- |
| `type="linear"` + `degree`              | `type: "linear"`, `degree`        |
| `type="path"` + `left/right/top/bottom` | `type: "path"`, four inset fields |
| `<stop position><color rgb=…/></stop>`  | `stops` array                     |

## Canvas rendering

The renderer constructs a `CanvasGradient` for each cell:

* **Linear**: the gradient axis projects through the cell's centroid at the given angle; start/end points are where that axis exits the bounding box.
* **Path / radial**: a `createRadialGradient` anchored at the inset midpoint with radius = distance to the farthest corner.

`setLineDash` and stroke styles are preserved — gradient cells still get cell borders, conditional-format icons, etc.

## Storybook example

See the `compatShowcaseSheet` in the storybook (Sheet 1, row 12) for a side-by-side gallery: `linear 0°`, `linear 90°`, `linear 45° (3 stops)`, `path (radial)`, `linear 180°`, and a `linear vert 3-stop` example. The pattern-fill row (row 11) is positioned right above so you can compare the two paint paths.
