Styling and Layout
The TVL chart accepts dozens of chart-level keyword arguments that control how the chart looks before any series is drawn: background colors, grid lines, crosshair behavior, fonts, and pane separators. Use this page when you want to match a brand palette, build a light/dark theme, or restyle the cursor and grid for a denser dashboard.
All styling kwargs in this guide live on chart() and on every convenience factory (candlestick(), line(), etc.). The chart wrapper accepts a compact subset of the styling parameters (background, text color, crosshair, watermark); the full surface lives on chart().
What are the styling options useful for?
- Theming: Build a light and dark palette by toggling background, text, and grid colors; the same chart code renders against either theme.
- Matching a brand: Override gradients, grid lines, and crosshair color to keep charts on-brand inside an existing UI.
- Dense dashboards: Tune font size, grid visibility, and pane separators so several charts can sit side by side without visual clutter.
- Accessibility: Adjust contrast and crosshair visibility for users who need higher-contrast or focus-style cues.
Examples
Apply a dark theme
The simplest theme switch is three colors: background, text, and grid. Pass them to chart() and the whole surface re-renders against the new palette. The grid is configured with a grid() object holding a grid_lines() for each axis, so you can color and style the two axes independently.
Pair background_color with text_color so axis labels stay legible against the new background.
Build a vertical gradient background
To render a gradient, swap background_color for the background_top_color / background_bottom_color pair. TVL renders a vertical gradient between the two stops. The two arguments must be used together; supplying only one falls back to the solid background path.
The ColorType enum values ("solid", "gradient") are inferred from which background arguments you set; there is no explicit color_type kwarg. The example above selects the gradient path:
Customize grid lines
The grid is two independent sets of lines: vertical (time-axis grid) and horizontal (price-axis grid). Each grid_lines() has visibility, color, and LineStyle controls. Pass tvl.grid_lines(visible=False) for one axis to hide that set while keeping the other.
LineStyle accepts "solid", "dotted", "dashed", "large_dashed", and "sparse_dotted".
Switch crosshair mode: normal, magnet, or hidden
The CrosshairMode enum controls how the cursor crosshair behaves on hover. "normal" follows the pointer freely; "magnet" snaps to the nearest data point; "hidden" removes the crosshair entirely. The fourth value, "magnet_ohlc", snaps to the nearest OHLC point on candlestick / bar charts.
Use "magnet" for sparse data where exact-point readouts matter; "normal" for continuous-feeling cursor tracking on dense data.
Tune the crosshair line and label
Beyond the mode, every crosshair line and label has its own color, width, style, and visibility options. Build a crosshair_line() for the vertical line (which crosses the time axis) and another for the horizontal line (which crosses the price axis), and pass them as vert_line= / horz_line= on crosshair().
The do_not_snap_to_hidden_series option on crosshair() is helpful in magnet mode when you want the crosshair to ignore series the user has toggled off.
Hover the active series on top
hovered_series_on_top re-orders the z-stack so the series the cursor is currently over draws above its siblings. The default is True, but you can disable it for fixed-layer charts where draw order needs to be deterministic.
This pairs well with crosshair "magnet" mode, since the snapped-to series moves to the top automatically.
Set the chart font
font_size controls the base axis-label font size in pixels. The font family is inherited from the host page; TVL does not expose a per-chart font-family override, since chart text is rendered to canvas and uses the closest available system stack.
Increase font_size for dashboard tiles viewed from a distance, or shrink it to fit dense small-multiples layouts.
TradingView attribution logo
This plugin hides the lightweight-charts attribution logo by default. Upstream says users should include the NOTICE attribution and a TradingView link on a page available to users; the built-in logo is one way to satisfy the link requirement. Set attribution_logo=True to show it.
Pick a wide-gamut color space
color_space selects the underlying canvas color space. The default "srgb" matches what every browser ships; "display-p3" opts in to the wide-gamut P3 space on capable displays, which gives richer reds and greens. Use it when your design system specifies P3 colors.
The two ColorSpace enum values are "srgb" and "display-p3".
Control scroll and zoom interactions
Pass tvl.scroll(...) / tvl.scale(...) to handle_scroll / handle_scale to enable or disable specific input gestures, such as mouse wheel zoom, touch drag, and double-click reset. handle_scroll and handle_scale also accept a plain bool to short-circuit all sub-options at once.
TrackingModeExitMode accepts "on_touch_end" and "on_next_tap".
The granular gesture controls live on the Scroll and Scale objects: tvl.scroll(...) toggles mouse_wheel, pressed_mouse_move, horz_touch_drag, and vert_touch_drag, while tvl.scale(...) toggles mouse_wheel, pinch, axis_pressed_mouse_move, and axis_double_click_reset. Pass a plain bool to handle_scroll / handle_scale to toggle everything at once.
Create a Scroll config for tvl.chart(handle_scroll=...).
Returns: Scroll A scroll-interaction config for tvl.chart(handle_scroll=...).
| Parameters | Type | Default | Description |
|---|---|---|---|
| mouse_wheel | bool | None | None | Allow mouse-wheel scrolling. |
| pressed_mouse_move | bool | None | None | Allow click-drag scrolling. |
| horz_touch_drag | bool | None | None | Allow horizontal touch scrolling. |
| vert_touch_drag | bool | None | None | Allow vertical touch scrolling. |
Create a Scale config for tvl.chart(handle_scale=...).
Returns: Scale A scale-interaction config for tvl.chart(handle_scale=...).
| Parameters | Type | Default | Description |
|---|---|---|---|
| mouse_wheel | bool | None | None | Allow zooming with the mouse wheel. |
| pinch | bool | None | None | Allow pinch-to-zoom on touch devices. |
| axis_pressed_mouse_move | bool | None | None | Allow scaling by dragging an axis. |
| axis_double_click_reset | bool | None | None | Reset axis scale on double-click. |
Switch last-price animation modes
LastPriceAnimationMode controls the pulse animation on the last-price marker for line / area / baseline series (candlestick / bar / histogram don’t have it). Use "disabled" for static snapshots, "continuous" to make the marker pulse continuously while the chart is visible, and "on_data_update" to pulse only when new data arrives.
The kwarg lives on the series factory, not on the chart-styling wrapper, so set it directly on tvl.line (or area / baseline):
The three values map directly to the LastPriceAnimationMode Literal alias. Use "disabled" wherever snapshot determinism matters; the other two introduce time-dependent rendering.
API Reference
Grid lines and the crosshair are configured with grouped objects: tvl.grid(...)
(holding a tvl.grid_lines(...) per axis) returns a Grid / GridLines, and
tvl.crosshair(...) (holding a tvl.crosshair_line(...) per line) returns a
Crosshair / CrosshairLine. Pass them to grid= and crosshair= on
tvl.chart(...). For the full tvl.chart signature, see the
Chart container page.
Create a chart Grid config for tvl.chart(grid=...).
Returns: Grid A grid config for tvl.chart(grid=...).
| Parameters | Type | Default | Description |
|---|---|---|---|
| vert | GridLines | None | None | Styling for the vertical gridlines. |
| horz | GridLines | None | None | Styling for the horizontal gridlines. |
Create GridLines styling for tvl.grid(vert=..., horz=...).
Returns: GridLines A gridline style config.
| Parameters | Type | Default | Description |
|---|---|---|---|
| visible | bool | None | None | Show the gridlines. |
| color | Literal['gray-50', 'gray-75', 'gray-100', 'gray-200', 'gray-300', 'gray-400', 'gray-500', 'gray-600', 'gray-700', 'gray-800', 'gray-900', 'red-100', 'red-200', 'red-300', 'red-400', 'red-500', 'red-600', 'red-700', 'red-800', 'red-900', 'red-1000', 'red-1100', 'red-1200', 'red-1300', 'red-1400', 'orange-100', 'orange-200', 'orange-300', 'orange-400', 'orange-500', 'orange-600', 'orange-700', 'orange-800', 'orange-900', 'orange-1000', 'orange-1100', 'orange-1200', 'orange-1300', 'orange-1400', 'yellow-100', 'yellow-200', 'yellow-300', 'yellow-400', 'yellow-500', 'yellow-600', 'yellow-700', 'yellow-800', 'yellow-900', 'yellow-1000', 'yellow-1100', 'yellow-1200', 'yellow-1300', 'yellow-1400', 'chartreuse-100', 'chartreuse-200', 'chartreuse-300', 'chartreuse-400', 'chartreuse-500', 'chartreuse-600', 'chartreuse-700', 'chartreuse-800', 'chartreuse-900', 'chartreuse-1000', 'chartreuse-1100', 'chartreuse-1200', 'chartreuse-1300', 'chartreuse-1400', 'celery-100', 'celery-200', 'celery-300', 'celery-400', 'celery-500', 'celery-600', 'celery-700', 'celery-800', 'celery-900', 'celery-1000', 'celery-1100', 'celery-1200', 'celery-1300', 'celery-1400', 'green-100', 'green-200', 'green-300', 'green-400', 'green-500', 'green-600', 'green-700', 'green-800', 'green-900', 'green-1000', 'green-1100', 'green-1200', 'green-1300', 'green-1400', 'seafoam-100', 'seafoam-200', 'seafoam-300', 'seafoam-400', 'seafoam-500', 'seafoam-600', 'seafoam-700', 'seafoam-800', 'seafoam-900', 'seafoam-1000', 'seafoam-1100', 'seafoam-1200', 'seafoam-1300', 'seafoam-1400', 'cyan-100', 'cyan-200', 'cyan-300', 'cyan-400', 'cyan-500', 'cyan-600', 'cyan-700', 'cyan-800', 'cyan-900', 'cyan-1000', 'cyan-1100', 'cyan-1200', 'cyan-1300', 'cyan-1400', 'blue-100', 'blue-200', 'blue-300', 'blue-400', 'blue-500', 'blue-600', 'blue-700', 'blue-800', 'blue-900', 'blue-1000', 'blue-1100', 'blue-1200', 'blue-1300', 'blue-1400', 'indigo-100', 'indigo-200', 'indigo-300', 'indigo-400', 'indigo-500', 'indigo-600', 'indigo-700', 'indigo-800', 'indigo-900', 'indigo-1000', 'indigo-1100', 'indigo-1200', 'indigo-1300', 'indigo-1400', 'purple-100', 'purple-200', 'purple-300', 'purple-400', 'purple-500', 'purple-600', 'purple-700', 'purple-800', 'purple-900', 'purple-1000', 'purple-1100', 'purple-1200', 'purple-1300', 'purple-1400', 'fuchsia-100', 'fuchsia-200', 'fuchsia-300', 'fuchsia-400', 'fuchsia-500', 'fuchsia-600', 'fuchsia-700', 'fuchsia-800', 'fuchsia-900', 'fuchsia-1000', 'fuchsia-1100', 'fuchsia-1200', 'fuchsia-1300', 'fuchsia-1400', 'magenta-100', 'magenta-200', 'magenta-300', 'magenta-400', 'magenta-500', 'magenta-600', 'magenta-700', 'magenta-800', 'magenta-900', 'magenta-1000', 'magenta-1100', 'magenta-1200', 'magenta-1300', 'magenta-1400', 'negative', 'notice', 'positive', 'info', 'accent', 'accent-100', 'accent-200', 'accent-300', 'accent-400', 'accent-500', 'accent-600', 'accent-700', 'accent-800', 'accent-900', 'accent-1000', 'accent-1100', 'accent-1200', 'accent-1300', 'accent-1400', 'bg', 'content-bg', 'subdued-content-bg', 'surface-bg', 'fg'] | str | None | None | Gridline CSS color. |
| style | Literal['solid', 'dotted', 'dashed', 'large_dashed', 'sparse_dotted'] | None | None | Dash pattern; see LineStyle. |
Create a Crosshair config for tvl.chart(crosshair=...).
Returns: Crosshair A crosshair config for tvl.chart(crosshair=...).
| Parameters | Type | Default | Description |
|---|---|---|---|
| mode | Literal['normal', 'magnet', 'hidden', 'magnet_ohlc'] | None | None | Tracking behavior; see CrosshairMode. |
| do_not_snap_to_hidden_series | bool | None | None | In magnet/snap modes, skip hidden series. |
| vert_line | CrosshairLine | None | None | Styling for the vertical crosshair line. |
| horz_line | CrosshairLine | None | None | Styling for the horizontal crosshair line. |
Create a CrosshairLine for tvl.crosshair(vert_line=..., horz_line=...).
Returns: CrosshairLine A crosshair-line style config.
| Parameters | Type | Default | Description |
|---|---|---|---|
| width | Literal[1, 2, 3, 4] | None | None | Line width in pixels; see LineWidth. |
| color | Literal['gray-50', 'gray-75', 'gray-100', 'gray-200', 'gray-300', 'gray-400', 'gray-500', 'gray-600', 'gray-700', 'gray-800', 'gray-900', 'red-100', 'red-200', 'red-300', 'red-400', 'red-500', 'red-600', 'red-700', 'red-800', 'red-900', 'red-1000', 'red-1100', 'red-1200', 'red-1300', 'red-1400', 'orange-100', 'orange-200', 'orange-300', 'orange-400', 'orange-500', 'orange-600', 'orange-700', 'orange-800', 'orange-900', 'orange-1000', 'orange-1100', 'orange-1200', 'orange-1300', 'orange-1400', 'yellow-100', 'yellow-200', 'yellow-300', 'yellow-400', 'yellow-500', 'yellow-600', 'yellow-700', 'yellow-800', 'yellow-900', 'yellow-1000', 'yellow-1100', 'yellow-1200', 'yellow-1300', 'yellow-1400', 'chartreuse-100', 'chartreuse-200', 'chartreuse-300', 'chartreuse-400', 'chartreuse-500', 'chartreuse-600', 'chartreuse-700', 'chartreuse-800', 'chartreuse-900', 'chartreuse-1000', 'chartreuse-1100', 'chartreuse-1200', 'chartreuse-1300', 'chartreuse-1400', 'celery-100', 'celery-200', 'celery-300', 'celery-400', 'celery-500', 'celery-600', 'celery-700', 'celery-800', 'celery-900', 'celery-1000', 'celery-1100', 'celery-1200', 'celery-1300', 'celery-1400', 'green-100', 'green-200', 'green-300', 'green-400', 'green-500', 'green-600', 'green-700', 'green-800', 'green-900', 'green-1000', 'green-1100', 'green-1200', 'green-1300', 'green-1400', 'seafoam-100', 'seafoam-200', 'seafoam-300', 'seafoam-400', 'seafoam-500', 'seafoam-600', 'seafoam-700', 'seafoam-800', 'seafoam-900', 'seafoam-1000', 'seafoam-1100', 'seafoam-1200', 'seafoam-1300', 'seafoam-1400', 'cyan-100', 'cyan-200', 'cyan-300', 'cyan-400', 'cyan-500', 'cyan-600', 'cyan-700', 'cyan-800', 'cyan-900', 'cyan-1000', 'cyan-1100', 'cyan-1200', 'cyan-1300', 'cyan-1400', 'blue-100', 'blue-200', 'blue-300', 'blue-400', 'blue-500', 'blue-600', 'blue-700', 'blue-800', 'blue-900', 'blue-1000', 'blue-1100', 'blue-1200', 'blue-1300', 'blue-1400', 'indigo-100', 'indigo-200', 'indigo-300', 'indigo-400', 'indigo-500', 'indigo-600', 'indigo-700', 'indigo-800', 'indigo-900', 'indigo-1000', 'indigo-1100', 'indigo-1200', 'indigo-1300', 'indigo-1400', 'purple-100', 'purple-200', 'purple-300', 'purple-400', 'purple-500', 'purple-600', 'purple-700', 'purple-800', 'purple-900', 'purple-1000', 'purple-1100', 'purple-1200', 'purple-1300', 'purple-1400', 'fuchsia-100', 'fuchsia-200', 'fuchsia-300', 'fuchsia-400', 'fuchsia-500', 'fuchsia-600', 'fuchsia-700', 'fuchsia-800', 'fuchsia-900', 'fuchsia-1000', 'fuchsia-1100', 'fuchsia-1200', 'fuchsia-1300', 'fuchsia-1400', 'magenta-100', 'magenta-200', 'magenta-300', 'magenta-400', 'magenta-500', 'magenta-600', 'magenta-700', 'magenta-800', 'magenta-900', 'magenta-1000', 'magenta-1100', 'magenta-1200', 'magenta-1300', 'magenta-1400', 'negative', 'notice', 'positive', 'info', 'accent', 'accent-100', 'accent-200', 'accent-300', 'accent-400', 'accent-500', 'accent-600', 'accent-700', 'accent-800', 'accent-900', 'accent-1000', 'accent-1100', 'accent-1200', 'accent-1300', 'accent-1400', 'bg', 'content-bg', 'subdued-content-bg', 'surface-bg', 'fg'] | str | None | None | Line CSS color. |
| style | Literal['solid', 'dotted', 'dashed', 'large_dashed', 'sparse_dotted'] | None | None | Dash pattern; see LineStyle. |
| visible | bool | None | None | Show the line. |
| label_visible | bool | None | None | Show the line's axis label. |
| label_background_color | Literal['gray-50', 'gray-75', 'gray-100', 'gray-200', 'gray-300', 'gray-400', 'gray-500', 'gray-600', 'gray-700', 'gray-800', 'gray-900', 'red-100', 'red-200', 'red-300', 'red-400', 'red-500', 'red-600', 'red-700', 'red-800', 'red-900', 'red-1000', 'red-1100', 'red-1200', 'red-1300', 'red-1400', 'orange-100', 'orange-200', 'orange-300', 'orange-400', 'orange-500', 'orange-600', 'orange-700', 'orange-800', 'orange-900', 'orange-1000', 'orange-1100', 'orange-1200', 'orange-1300', 'orange-1400', 'yellow-100', 'yellow-200', 'yellow-300', 'yellow-400', 'yellow-500', 'yellow-600', 'yellow-700', 'yellow-800', 'yellow-900', 'yellow-1000', 'yellow-1100', 'yellow-1200', 'yellow-1300', 'yellow-1400', 'chartreuse-100', 'chartreuse-200', 'chartreuse-300', 'chartreuse-400', 'chartreuse-500', 'chartreuse-600', 'chartreuse-700', 'chartreuse-800', 'chartreuse-900', 'chartreuse-1000', 'chartreuse-1100', 'chartreuse-1200', 'chartreuse-1300', 'chartreuse-1400', 'celery-100', 'celery-200', 'celery-300', 'celery-400', 'celery-500', 'celery-600', 'celery-700', 'celery-800', 'celery-900', 'celery-1000', 'celery-1100', 'celery-1200', 'celery-1300', 'celery-1400', 'green-100', 'green-200', 'green-300', 'green-400', 'green-500', 'green-600', 'green-700', 'green-800', 'green-900', 'green-1000', 'green-1100', 'green-1200', 'green-1300', 'green-1400', 'seafoam-100', 'seafoam-200', 'seafoam-300', 'seafoam-400', 'seafoam-500', 'seafoam-600', 'seafoam-700', 'seafoam-800', 'seafoam-900', 'seafoam-1000', 'seafoam-1100', 'seafoam-1200', 'seafoam-1300', 'seafoam-1400', 'cyan-100', 'cyan-200', 'cyan-300', 'cyan-400', 'cyan-500', 'cyan-600', 'cyan-700', 'cyan-800', 'cyan-900', 'cyan-1000', 'cyan-1100', 'cyan-1200', 'cyan-1300', 'cyan-1400', 'blue-100', 'blue-200', 'blue-300', 'blue-400', 'blue-500', 'blue-600', 'blue-700', 'blue-800', 'blue-900', 'blue-1000', 'blue-1100', 'blue-1200', 'blue-1300', 'blue-1400', 'indigo-100', 'indigo-200', 'indigo-300', 'indigo-400', 'indigo-500', 'indigo-600', 'indigo-700', 'indigo-800', 'indigo-900', 'indigo-1000', 'indigo-1100', 'indigo-1200', 'indigo-1300', 'indigo-1400', 'purple-100', 'purple-200', 'purple-300', 'purple-400', 'purple-500', 'purple-600', 'purple-700', 'purple-800', 'purple-900', 'purple-1000', 'purple-1100', 'purple-1200', 'purple-1300', 'purple-1400', 'fuchsia-100', 'fuchsia-200', 'fuchsia-300', 'fuchsia-400', 'fuchsia-500', 'fuchsia-600', 'fuchsia-700', 'fuchsia-800', 'fuchsia-900', 'fuchsia-1000', 'fuchsia-1100', 'fuchsia-1200', 'fuchsia-1300', 'fuchsia-1400', 'magenta-100', 'magenta-200', 'magenta-300', 'magenta-400', 'magenta-500', 'magenta-600', 'magenta-700', 'magenta-800', 'magenta-900', 'magenta-1000', 'magenta-1100', 'magenta-1200', 'magenta-1300', 'magenta-1400', 'negative', 'notice', 'positive', 'info', 'accent', 'accent-100', 'accent-200', 'accent-300', 'accent-400', 'accent-500', 'accent-600', 'accent-700', 'accent-800', 'accent-900', 'accent-1000', 'accent-1100', 'accent-1200', 'accent-1300', 'accent-1400', 'bg', 'content-bg', 'subdued-content-bg', 'surface-bg', 'fg'] | str | None | None | Axis-label background color. |