Gradient cell fills

Linear and radial gradient fills on individual cells — round-trips XLSX and renders on canvas

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

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:

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

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.

Last updated