---
url: https://chartbuddy.io/embed/docs/chart-types/line.md
---
# Line

Trends over an ordered domain – one polyline per series.

## Identity

| | |
|---|---|
| `chartType` | `line` |
| Option bag | `line` |
| `seriesData` layout | `seriesRows` – row 0 = category header; later rows = series |
| Min grid | 2 rows × 2 columns (header included) |
| Orientation | Yes – `vertical` (default) or `horizontal` |
| Sample | [Line](/samples/line) · [Dual-axis line](/samples/dual-axis-line) |

***

## Minimal `chartData`

```js
{
  chartType: 'line',
  isDataTransposed: true,
  seriesData: [
    ['', 'Jan', 'Feb', 'Mar', 'Apr'],
    ['Visits', 120, 132, 128, 150],
  ],
  title: { visible: true, text: 'Weekly visits' },
  subtitle: { visible: false, text: '' },
  legend: { visible: false },
}
```

***

## `seriesData`

Same `seriesRows` layout as clustered bar (with `isDataTransposed: true`):

```js
[
  ['', 'Jan', 'Feb', 'Mar', 'Apr'],
  ['Visits', 120, 132, 128, 150],
  ['Signups', 40, 44, 41, 55],
]
```

| Rule | Detail |
|---|---|
| Row 0 | Ordered domain labels (categories / periods) |
| Later rows | One series each |
| Empty / `null` cells | Breaks in the line for that point (intentional gaps) |

Shared layout rules: [chartData schema · seriesData](/api/chart-data#seriesdata-layouts).

***

## Option bag: `line`

Only `chartType: 'line'` reads **`cd.line`**. Stacked areas use the separate `area` bag.

| Field | Default (new charts) | Role |
|---|---|---|
| `width` | `2` | Stroke width (px) |
| `strokeDashArray` | `''` | Dash pattern (SVG-style string) |
| `drawPoints` | `false` | Show point markers on the line |
| `curveParameter` | `0.85` | Curve tension (editor **Smoothness** control) |
| `shadowIntensity` | `0` | Soft shadow under the stroke |
| `pointMarker` | see below | Marker style when `drawPoints` is on |
| `overrides` | `{}` | Indexed style patches |

Leave `curveType` at its default (`'cardinal'`). Prefer adjusting **`curveParameter`** (editor Smoothness) rather than swapping interpolation names.

### Point markers

Rendered only when `drawPoints: true`. Resolution order: per-point override → per-series → global `pointMarker`.

```js
{
  chartType: 'line',
  seriesData: [/* … */],
  line: {
    width: 2.5,
    drawPoints: true,
    curveParameter: 0.85,
    pointMarker: {
      shape: 'circle', // circle | square | diamond | triangle
      radius: 3,
      fill: null,      // null = series color
      stroke: '#ffffff',
      strokeWidth: 1,
    },
  },
}
```

Full marker surface: [Point markers](/configuration/point-markers).

***

## Axes & scales

| Role | Vertical (default) | Horizontal |
|---|---|---|
| Domain | `bottom` | `left` |
| Primary range | `left` | `bottom` |
| Secondary range | `right` | `top` |

* Dual-axis is fully supported on line charts: enable the secondary range axis and set `boundSeries` to the series indices that use it.
* Setting the range axis with `customMin` / `customMax` is normal (unlike bars, which bias toward including zero).
* Pair tick formats and `preferredTickInterval` with the side that holds the range role after orientation.

Details: [Axes · Secondary](/axes/secondary) · [Axes · by chart type](/axes/by-chart-type) · [Dual-axis line sample](/samples/dual-axis-line).

```js
{
  chartType: 'line',
  isDataTransposed: true,
  seriesData: [
    ['', 'Q1', 'Q2', 'Q3', 'Q4'],
    ['Revenue', 120, 140, 155, 170],
    ['Margin %', 18, 19, 21, 20],
  ],
  axes: {
    right: {
      id: 'secondaryRange',
      enabled: true,
      visible: true,
      boundSeries: [1],
      labels: {
        preferredTickInterval: 5,
        numberFormat: {
          mode: 'custom',
          customFormat: {
            prefix: '',
            postfix: '%',
            thousandSeparator: ',',
            decimalSeparator: '.',
            decimalPlaces: 0,
            forceDecimals: false,
            signDisplay: 'auto',
            scaleDown: 0,
          },
        },
      },
    },
  },
}
```

***

## Type-specific behaviour

* Series color still comes from `legend.colors`.
* Markers stay off until `line.drawPoints: true` (or you turn them on in the editor).
* For bar + line on one chart, use [`combo`](/chart-types/combo) with `combo.seriesTypes` – do not put bar options in `cd.line`.
* Area fills belong on `stackedArea` / `cd.area`, not on `line`.

***

## Pitfalls

* Expecting markers without `drawPoints: true`
* Putting area/bar fields on `line` (`foreign-option-bag`)
* Binding secondary with the wrong series index after reordering rows
* Forcing bar-style “must include zero” when a tighter range-axis span is what you want – set `customMin` / `customMax` deliberately ([Value axis](/axes/value-axis))
* Using `stackedArea` defaults/`area` bag when you only wanted a stroke

***

## Related

* [Stacked area](/chart-types/stacked-area) · [Combo](/chart-types/combo) · [Point markers](/configuration/point-markers)
* [chartData schema](/api/chart-data) · [Axes](/axes/)
* Samples: [Line](/samples/line) · [Dual-axis line](/samples/dual-axis-line) · [Percent axis](/samples/percent-axis)
