Crosshair & legend
subscribeCrosshairMove fires the hovered bar of the primary price series on every cursor
move (and all-null fields on pointer-leave), so your app renders the legend or tooltip in its
own DOM - the engine never imposes a legend style.
const unsub = chart.subscribeCrosshairMove((e) => {
const bar = e.bar ?? bars.at(-1); // e.bar is null when the cursor leaves
legendEl.textContent = bar
? `O ${bar.open} H ${bar.high} L ${bar.low} C ${bar.close}`
: '';
// e.point gives container-relative px to position a floating tooltip
});Live OHLC legend
Hover the chart - the legend in the top-left tracks the bar under the crosshair:
live
Rendering live chart…
Move your cursor across the chart to update the legend.
View example code
const chart = lib.createChart(el);
const bars = lib.generateBars(1700000000, 160, 3600);
chart.addSeries('candlestick').setData(bars);
el.style.position = 'relative';
const legend = document.createElement('div');
legend.style.cssText = 'position:absolute;left:12px;top:10px;z-index:4;font:600 12px ui-monospace,monospace;color:#cbd5e1;pointer-events:none';
el.appendChild(legend);
function render(b) {
legend.textContent = b
? ('O ' + b.open.toFixed(2) + ' H ' + b.high.toFixed(2) + ' L ' + b.low.toFixed(2) + ' C ' + b.close.toFixed(2))
: '';
}
render(bars[bars.length - 1]);
chart.subscribeCrosshairMove(function (e) { render(e.bar || bars[bars.length - 1]); });
chart.timeScale.fitContent(bars.length);
return chart;The crosshair itself is global (a thin vertical line across all panes) with price and time axis tags. Its time tag shows seconds on sub-minute timeframes.