Skip to main content
v2.2

Container

Container is a component for flexible grid-based positioning of multiple Charts with overlay support in the same rendering view. Containers use CSS Grid layout for chart positioning and support features like scrollable layouts and custom dimensions.

Containers are created with the lc.Container() function. Upon creation, the number of columns and rows must be specified. Charts can then be placed in container cells with column and row indexes and spans:

import lightningchart as lc
import numpy as np
import pandas as pd

lc.set_license('my-license-key')

cont = lc.Container(
theme=lc.Themes.Light,
columns=5,
rows=4,
width='100%',
height='200vh',
)

chart1 = cont.ChartXY(column_index=0, row_index=0, column_span=5)
chart2 = cont.ChartXY(column_index=0, row_index=1, column_span=5)
chart3 = cont.ChartXY(column_index=0, row_index=2, column_span=5)
chart4 = cont.ChartXY(column_index=0, row_index=3, column_span=5)

now = pd.Timestamp.now().normalize()

def last_days(n, x_ms):
end = x_ms[-1]
start = pd.Timestamp(now - pd.Timedelta(days=n)).value // 10**6
start = max(start, x_ms[0])
return start, end

def one_year(x_ms):
return last_days(365, x_ms)

# Generate Data
start_date = now - pd.Timedelta(days=720)
dates = pd.date_range(start_date, now, freq='D')
n = len(dates)
x_ms = (dates.astype('int64') // 10**6).astype('int64').tolist()
np.random.seed(0)

# Chart 1: Random Walk
chart1.set_title('Chart 1: Random Walk')
x_axis1 = chart1.get_default_x_axis().set_tick_strategy('DateTime')
vals1 = np.cumsum(np.random.normal(0, 1, n)) + 50
series1 = chart1.add_point_line_series().set_name('Random Walk')
series1.append_samples(x_values=x_ms, y_values=vals1.astype(float).tolist())

# Chart 2: Sine Wave with Noise
chart2.set_title('Chart 2: Sine Wave + Noise')
x_axis2 = chart2.get_default_x_axis().set_tick_strategy('DateTime')
vals2 = 50 + 20 * np.sin(np.linspace(0, 8 * np.pi, n)) + np.random.normal(0, 3, n)
series2 = chart2.add_point_line_series().set_name('Sine Wave')
series2.append_samples(x_values=x_ms, y_values=vals2.astype(float).tolist())
series2.set_line_color(color=(100, 200, 255)).set_line_thickness(2)

# Chart 3: Exponential Growth
chart3.set_title('Chart 3: Exponential Growth')
x_axis3 = chart3.get_default_x_axis().set_tick_strategy('DateTime')
vals3 = 10 * np.exp(np.linspace(0, 3, n)) + np.random.normal(0, 10, n)
series3 = chart3.add_point_line_series().set_name('Exponential')
series3.append_samples(x_values=x_ms, y_values=vals3.astype(float).tolist())

# Chart 4: Multiple Series
chart4.set_title('Chart 4: Multiple Trends')
x_axis4 = chart4.get_default_x_axis().set_tick_strategy('DateTime')
vals4a = np.cumsum(np.random.normal(0.1, 1, n)) + 30
vals4b = np.cumsum(np.random.normal(-0.05, 1.2, n)) + 50
vals4c = np.cumsum(np.random.normal(0.05, 0.8, n)) + 40

series4a = chart4.add_point_line_series().set_name('Trend A')
series4a.append_samples(x_values=x_ms, y_values=vals4a.astype(float).tolist())

series4b = chart4.add_point_line_series().set_name('Trend B')
series4b.append_samples(x_values=x_ms, y_values=vals4b.astype(float).tolist())

series4c = chart4.add_point_line_series().set_name('Trend C')
series4c.append_samples(x_values=x_ms, y_values=vals4c.astype(float).tolist())

# Initialize all charts to 1 year view
all_x_axes = [x_axis1, x_axis2, x_axis3, x_axis4]

def set_all_intervals_to_one_year():
lo, hi = one_year(x_ms)
for ax in all_x_axes:
ax.set_interval(lo, hi, stop_axis_after=False)

# Synchronize all x-axes
chart1.synchronize_axis_intervals(all_x_axes)
set_all_intervals_to_one_year()

cont.open()

Container vs Dashboard

Container and Dashboard share similar APIs and chart positioning capabilities. Both use grid-based layouts and support the same chart types with identical methods.

Use Container when:

  • You need custom dimensions (pixel or CSS units like 100vw, 200vh)
  • You require scrollable layouts for tall dashboards
  • You want explicit control over container sizing

Use Dashboard when:

  • You want standard full-viewport layouts (no internal scrolling or explicit sizing).

Both components support:

  • Cell spanning with column_span and row_span
  • Theme-aware styling

Example comparison:

# Dashboard - full viewport, LCJS native
dashboard = lc.Dashboard(theme=lc.Themes.Dark, columns=2, rows=2)

# Container - custom dimensions, scrollable
container = lc.Container(
theme=lc.Themes.Dark,
columns=2,
rows=2,
width=1920,
height=2000,
scrollable=True
)

Both produce similar grid layouts, but Container offers more flexibility for custom viewport requirements.