---
title: Area Charts in Python
description: Fill trends to a baseline with area charts, and show piecewise-constant states with step and stairs charts in Python using xy.
components:
  - xy.area_chart
  - xy.step_chart
  - xy.stairs_chart
---

# Area, Step, and Stairs Charts in Python

> Looking for line charts? See the dedicated
> [line chart guide](/docs/xy/charts/line-chart/).

## When to Use

Use an `area` chart (also called an area plot or area graph) when the magnitude
relative to a baseline matters, `step` for state
changes attached to samples, and `stairs` when you already have bin edges. All
support screen-space dash patterns, opacity, and named axes. For a plain trend
line, use a [line chart](/docs/xy/charts/line-chart/); for isolated impulses,
use a [stem plot](/docs/xy/charts/stem-plot/).

## Live Demo

~~~python demo exec
import numpy as np
import reflex_xy
import xy

x = np.linspace(0, 12, 240)
plan = 48 + 1.8 * x
actual = plan + 7 * np.sin(x * 0.9)

chart = xy.chart(
    xy.area(
        x,
        actual,
        name="Actual",
        color="#6e56cf",
        fill="linear-gradient(currentColor, transparent)",
        opacity=0.42,
        curve="smooth",
    ),
    xy.line(x, plan, name="Plan", color="#2563eb", dash="dashed"),
    xy.x_axis(label="month"),
    xy.y_axis(label="revenue"),
    xy.legend(),
)


def plan_and_actual():
    return reflex_xy.chart(chart, height="320px")
~~~

## Chart Types

### Area

Use `area` when the magnitude relative to a baseline matters. Its `base` can be
a scalar, array, or named column, and an optional perimeter line can keep the
upper boundary readable.

### Step and Stairs

Use `step` when each x/y observation defines a piecewise-constant state. Use
`stairs` when the values describe bins and you have explicit bin edges. Both
support `where="pre"`, `"mid"`, or `"post"` to control where transitions occur.

~~~python demo exec
import reflex_xy
import xy

chart = xy.chart(
    xy.step(
        [0, 1, 2, 3, 4, 5],
        [3.0, 4.5, 3.8, 5.4, 4.7, 6.2],
        where="post",
        name="Sampled state",
        color="#6e56cf",
        width=2.5,
    ),
    xy.stairs(
        values=[1.0, 2.2, 1.5, 2.8, 2.1],
        edges=[0, 1, 2, 3, 4, 5],
        name="Binned level",
        color="#2563eb",
        width=2.5,
        dash="dashed",
    ),
    xy.x_axis(label="time"),
    xy.y_axis(label="value"),
    xy.legend(),
    title="Step and stairs",
)


def step_and_stairs_demo():
    return reflex_xy.chart(chart, height="320px")
~~~

## Stacked Areas with an Array Base

Stack series by passing the running total of the layers below as each area's
`base`, and set `stroke_perimeter=True` with a `line_width` to keep every upper
boundary readable:

~~~python demo exec
import numpy as np
import reflex_xy
import xy

rng_stack = np.random.default_rng(5)
months = np.arange(0, 12, dtype=float)
mobile = 20 + 1.6 * months + rng_stack.normal(0.0, 1.0, months.size)
desktop = 34 + 0.7 * months + rng_stack.normal(0.0, 1.2, months.size)

stacked_area_chart = xy.chart(
    xy.area(
        months,
        mobile,
        name="Mobile",
        color="#6e56cf",
        opacity=0.55,
        stroke_perimeter=True,
        line_width=1.5,
    ),
    xy.area(
        months,
        mobile + desktop,
        base=mobile,
        name="Desktop",
        color="#2563eb",
        opacity=0.55,
        stroke_perimeter=True,
        line_width=1.5,
    ),
    xy.x_axis(label="month"),
    xy.y_axis(label="sessions (k)"),
    xy.legend(),
    title="Traffic by platform",
)


def stacked_area_demo():
    return reflex_xy.chart(stacked_area_chart, height="320px")
~~~

## Variants

- Layer several named `line` or `area` marks and add `legend()`.
- Use `curve="smooth"` for interpolation or `dash` for plan/actual comparisons.
- Set `where="pre"`, `"mid"`, or `"post"` on `step` and `stairs` for
  discrete signals.
- Bind marks to named axes for series with different units.

## Expected Data Shape

Pass one-dimensional x and y arrays of equal length, or pass column names with
`data=`. `area` also accepts a scalar, array, or named-column `base`. Missing
numeric values create line gaps. `step` uses the same x/y shape. `stairs` takes
one value per bin and, when supplied, one more edge than values.

## Key Options

`line` uses `color`, `width`, `opacity`, `curve`, and `dash`. `area` adds
`fill`, `base`, `stroke_perimeter`, `line_width`, and `line_opacity`.
`step` and `stairs` add `where="pre"`, `"mid"`, or `"post"`; `stairs` also
accepts `edges` and otherwise generates integer edges.

For very long lines, XY decimates to the visible resolution and refines again
when the viewport changes.

## FAQ

### How do I make an area chart in Python?

Call `xy.area(x, y)` inside a chart and render it; set `base` to fill from a
non-zero baseline and `fill` for a gradient.

### What is the difference between a step chart and a stairs chart?

`step` draws piecewise-constant states from x/y samples; `stairs` draws levels
from explicit bin edges. Both use `where="pre"`, `"mid"`, or `"post"` to place
transitions.

### How do I fill the area under a line in Python?

Use an `xy.area` mark instead of (or beneath) `xy.line`; its `fill` accepts a
solid color or a gradient such as `linear-gradient(currentColor, transparent)`.

### How do I show a plan-versus-actual comparison?

Layer an `area` for the actual values with a dashed `line` (`dash="dashed"`) for
the plan, and add `xy.legend()` to label them.
