# Target lines and bands

> Draw goals, limits, ranges and trends on line and bar charts with the targetLine(), band() and trendLine() layers, on a preset or in a composed chart.

A number on its own says little. Is 950 good? Against a goal of 1000, you see it at a glance. Two layers draw that context: `targetLine()` for goals and limits, `band()` for ranges. Both are part of the core, work on the presets and in composed charts, and you style them with CSS like the rest of the chart.

## A target line

Presets take extra layers in their `layers` option: `above` draws them on top of the bars or lines, `below` behind them.

**A goal line** (runs in the browser):

`src/main.ts`:

```ts
import 'chartist/styles.css';
import { barChart, targetLine } from 'chartist';

barChart(
  '#chart',
  {
    labels: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun'],
    series: [[820, 950, 1100, 760, 1240, 980]]
  },
  {
    low: 0,
    // Extra layers on top of the bars.
    layers: { above: [targetLine({ value: 1000, label: 'Goal' })] }
  }
);
```

`index.html`:

```html
<!doctype html>
<html>
  <head>
    <meta charset="UTF-8" />
    <script type="module" src="/src/main.ts"></script>
  </head>
  <body>
    <div id="chart" class="ct-golden-section"></div>
  </body>
</html>
```

[Responsive options](https://chartist.dev/docs/responsive/) can change the layers too: a `layers: { above: [...] }` entry replaces the `above` list and keeps `below`.

The Y axis makes room for the line: a goal above all the bars still shows. A `low` or `high` you set on the axis wins, and a line outside it isn't drawn.

| Option          | What it does                                                              |
| --------------- | ------------------------------------------------------------------------- |
| `value`         | Where the line goes, on the axis                                          |
| `label`         | Text next to the line (optional)                                          |
| `className`     | Extra class for the line and its label, such as `ct-series-b` for a color |
| `axis`          | The id of the axis the value is on; by default the first Y axis           |
| `labelPosition` | `'end'` (default) or `'start'` of the line                                |

### Several lines, and vertical ones

One layer draws one line. For a minimum and a goal, add two:

```ts
import { targetLine } from 'chartist';

export const limits = [
  targetLine({ value: 1000, label: 'Goal' }),
  targetLine({ value: 800, label: 'Minimum', className: 'ct-series-b' })
];
```

On an X axis, the lines are vertical. That's where the values are on horizontal bars: the presets call their axes `x` and `y`, so use `targetLine({ axis: 'x', value: 1000 })`. In a [composed chart](https://chartist.dev/docs/composed-charts/), use your own axis ids.

## Band charts

A band shows a range: from the lowest to the highest value of a group, between two series such as percentiles, or between two fixed values. With the group's average and one member drawn on top, you get a [band chart](https://www.clearlyandsimply.com/2011/04/an-underrated-chart-type-the-band-chart/): how does Bern do compared to the other stores?

**A band chart** (runs in the browser):

`src/main.ts`:

```ts
import 'chartist/styles.css';
import {
  autoScaleAxis,
  axisGrid,
  axisLabels,
  band,
  cartesianAxes,
  chart,
  line,
  stepAxis
} from 'chartist';

const weeks = ['W1', 'W2', 'W3', 'W4', 'W5', 'W6', 'W7', 'W8'];

// Weekly sales of six stores, in thousands.
const stores = [
  { name: 'Basel', data: [42, 45, 40, 38, 44, 47, 50, 52] },
  { name: 'Bern', data: [36, 38, 33, 28, 30, 41, 49, 55] },
  { name: 'Chur', data: [25, 27, 30, 29, 31, 30, 33, 34] },
  { name: 'Geneva', data: [50, 53, 55, 51, 49, 54, 58, 60] },
  { name: 'Lucerne', data: [31, 30, 34, 36, 35, 37, 36, 40] },
  { name: 'Zurich', data: [46, 44, 49, 52, 50, 48, 53, 57] }
];
const average = weeks.map(
  (_, week) =>
    stores.reduce((sum, store) => sum + store.data[week], 0) / stores.length
);

chart('#chart', {
  data: {
    labels: weeks,
    series: [
      ...stores,
      { name: 'average', className: 'ct-series-e', data: average }
    ]
  },
  axes: cartesianAxes({
    x: { type: stepAxis() },
    y: { type: autoScaleAxis(), low: 0 }
  }),
  layers: [
    axisGrid(),
    // From the lowest to the highest store, every week.
    band({ series: stores.map(store => store.name), lineSmooth: false }),
    line({ series: ['average'], lineSmooth: false, showPoint: false }),
    line({ series: ['Bern'], lineSmooth: false }),
    axisLabels()
  ]
});
```

`index.html`:

```html
<!doctype html>
<html>
  <head>
    <meta charset="UTF-8" />
    <script type="module" src="/src/main.ts"></script>
  </head>
  <body>
    <div id="chart" class="ct-golden-section"></div>
  </body>
</html>
```

`band({ series })` takes the group by name or index and covers its minimum to its maximum at each label. The average is a series you compute yourself: one line of code, and you decide what "average" means. Layers draw in order, so the band comes before the lines.

The edges of a band can be:

- **values of their own:** `band({ low: [3, 4, 3, 5], high: [9, 11, 10, 12] })`, one per label, like a series that isn't in your data,
- **two numbers:** `band({ low: 40, high: 60 })`, a target zone across the whole chart,
- **two series** from your data: `band({ low: 'p10', high: 'p90' })`,
- **a mix:** `band({ low: 0, high: forecast })`.

A number is a constant, an array holds values, and a string names a series; pick a series by index with `{ series: 2 }`.

Edges follow `lineSmooth` like lines do, smooth by default, and `align: 'center'` lines a band up with bars, as for [lines](https://chartist.dev/docs/composed-charts/#lining-up-with-bars). Where an edge has no value, the band breaks.

### On a preset

Give a preset's band its own values. The edges then stay out of your data, so the preset doesn't draw them as lines and the series keep their colors:

```ts
import { band, lineChart } from 'chartist';

lineChart(
  '#chart',
  {
    labels: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri'],
    series: [[5, 8, 6, 9, 7]]
  },
  {
    layers: {
      below: [band({ low: [3, 4, 3, 5, 4], high: [9, 11, 10, 12, 11] })]
    }
  }
);
```

On a scale X axis (an XY chart), give the values as `{ x, y }`, like the data.

## In or out of the band

With `mark: true`, the band marks the points and bars of the other layers: `ct-in-band` when the value is within the band, edges included, `ct-out-band` when it isn't. What "out" looks like is up to your CSS.

**A comfort zone** (runs in the browser):

`src/main.ts`:

```ts
import 'chartist/styles.css';
import './style.css';
import { band, lineChart } from 'chartist';

// Room temperature every two hours, and the range it should stay in.
lineChart(
  '#chart',
  {
    labels: [
      '0h',
      '2h',
      '4h',
      '6h',
      '8h',
      '10h',
      '12h',
      '14h',
      '16h',
      '18h',
      '20h',
      '22h'
    ],
    series: [[18, 17.5, 17, 17, 19, 21, 22.5, 24.5, 25, 23, 21, 19.5]]
  },
  {
    low: 15,
    high: 27,
    layers: { below: [band({ low: 19, high: 24, mark: true })] }
  }
);
```

`src/style.css`:

```css
/* Mustard yellow inside the band; outside, larger and in the series color. */
#chart .ct-point.ct-in-band {
  stroke: #f4c63d;
}

#chart .ct-point.ct-out-band {
  stroke-width: 14px;
}
```

`index.html`:

```html
<!doctype html>
<html>
  <head>
    <meta charset="UTF-8" />
    <script type="module" src="/src/main.ts"></script>
  </head>
  <body>
    <div id="chart" class="ct-golden-section"></div>
  </body>
</html>
```

The band marks the points no matter where it's listed: it works from the data, after every layer has drawn. Marking classes whole points and bars; a line keeps one color where it crosses an edge.

## Trend lines

`trendLine()` fits a straight line through each series it picks (all of them by default) and draws it from the series' first to its last value, dashed and in the series' color. The fit is least squares: on a step axis it uses the values' order, on a scale axis their `x`.

```ts
import { lineChart, trendLine } from 'chartist';

lineChart(
  '#chart',
  {
    labels: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun'],
    series: [[3, 5, 4, 7, 6, 9]]
  },
  { layers: { above: [trendLine()] } }
);
```

Where the line ends below or above the values, the Y axis grows to keep it in view. Holes are skipped, and a series with fewer than two values gets no line. On bar charts, `align: 'center'` lines it up with the bars, as for [lines](https://chartist.dev/docs/composed-charts/#lining-up-with-bars). Its role is `trendLine`, with the `slope` and `intercept` in its context. In the gallery: [bars with a trend line](https://chartist.dev/examples/composed/trend-line/) and [a scatter plot with a regression line](https://chartist.dev/examples/composed/scatter-regression/).

## Styling

The target line and the band draw in the text color by default: a dashed target line and a light band, so they read as context behind the data. Change them with custom properties, or give them a series color with `className: 'ct-series-c'`:

```css
.ct-chart {
  --ct-target-line-color: #c8102e;
  --ct-target-line-width: 2px;
  --ct-target-line-dasharray: none;
  --ct-band-color: #b07800;
  --ct-band-opacity: 0.2;
}
```

A trend line takes its series' color; `--ct-trend-line-width` and `--ct-trend-line-dasharray` change its look.

The markup: a `line.ct-target-line` and a `text.ct-target-label` per target line, a `line.ct-trend-line` in a series group per trend line, and a `g.ct-band` group with a `path.ct-band-area` per piece of the band. In listeners and plugins, find them by the roles `targetLine`, `targetLabel`, `trendLine` and `band`, as in [events and plugins](https://chartist.dev/docs/events-and-plugins/).

> **Coming from the target line plugin?** `chartist-plugin-targetline` with
> `{ value: 1000 }` becomes `layers: { above: [targetLine({ value: 1000 })] }`.
> The line keeps the class `ct-target-line`, so your CSS still applies. You
> also get labels, any axis, and server rendering.

Next: [compose your own charts](https://chartist.dev/docs/composed-charts/) with several axes, or [style the chart](https://chartist.dev/docs/styling-with-css/) to match your page.
