Skip to content

Title and subtitle

title and subtitle are drawn around the plot. Both accept the same options: text, font, color, alignment, vertical placement and the gap towards the plot.

ts
import { getData } from './data';
import type { ChartOptions } from 'grafit-charts';

// Custom caption fonts, colors and spacing.
export function createOptions(): ChartOptions {
  return {
    data: getData(),
    title: { text: 'Annual revenue', fontSize: 22, fontWeight: 800, color: '#0f766e', spacing: 4 },
    subtitle: { text: 'by quarter, $K', fontSize: 14, color: '#94a3b8', spacing: 16 },
    series: [{ type: 'bar', xField: 'quarter', yField: 'revenue', name: 'Revenue' }],
    legend: { enabled: false },
  };
}
ts
export function getData() {
  return [
    { quarter: 'Q1', revenue: 210 },
    { quarter: 'Q2', revenue: 265 },
    { quarter: 'Q3', revenue: 248 },
    { quarter: 'Q4', revenue: 312 },
  ];
}

Options

OptionTypeDefaultDescription
textstringcaption text
enabledbooleantrueshow the caption
textAlign'left' | 'center' | 'right''center'alignment within the chart width (snaps to the chart padding)
position'top' | 'bottom''top'above or below the plot
fontSizePixels17 / 13title / subtitle font size
fontWeightFontWeight'bold' / 'normal'font weight
fontFamilystringtheme fontfont family
colorColorValueforeground / mutedtext color
spacingPixels8gap between the caption and the plot

Alignment and placement

textAlign positions the caption within the chart width, snapping to the chart padding; position moves it above or below the plot. The title and subtitle are configured independently — mix them freely, e.g. a left-aligned title on top with a footnote-style subtitle at the bottom right:

ts
import { getData } from './data';
import type { ChartOptions } from 'grafit-charts';

// Left-aligned title on top, a footnote-style subtitle at the bottom right.
export function createOptions(): ChartOptions {
  return {
    data: getData(),
    title: { text: 'Weekly sessions', textAlign: 'left', spacing: 12 },
    subtitle: { text: 'updated hourly', textAlign: 'right', position: 'bottom' },
    series: [{ type: 'area', xField: 'day', yField: 'sessions', name: 'Sessions' }],
    legend: { enabled: false },
  };
}
ts
export function getData() {
  return [
    { day: 'Mon', sessions: 320 },
    { day: 'Tue', sessions: 356 },
    { day: 'Wed', sessions: 402 },
    { day: 'Thu', sessions: 384 },
    { day: 'Fri', sessions: 441 },
    { day: 'Sat', sessions: 268 },
    { day: 'Sun', sessions: 214 },
  ];
}

When both captions share a zone, the title always stays above the subtitle; spacing faces the plot.

A left-aligned title pairs well with a floating legend pinned to the opposite corner on the same level:

ts
import { getData } from './data';
import type { ChartOptions } from 'grafit-charts';

// A floating legend anchored to the top-right corner of the whole chart —
// on the same level as the left-aligned title.
export function createOptions(): ChartOptions {
  return {
    data: getData(),
    title: { text: 'Site traffic', textAlign: 'left', spacing: 4 },
    subtitle: { text: 'visits per month, thousands', textAlign: 'left', spacing: 12 },
    series: [
      { type: 'line', xField: 'month', yField: 'organic', name: 'Organic' },
      { type: 'line', xField: 'month', yField: 'ads', name: 'Ads' },
    ],
    legend: {
      position: 'top-right',
      floating: true,
      background: { fill: 'rgba(255, 255, 255, 0.85)', stroke: '#cbd5e1', cornerRadius: 6, padding: 10 },
    },
  };
}
ts
export function getData() {
  return [
    { month: 'Jan', organic: 42, ads: 18 },
    { month: 'Feb', organic: 48, ads: 22 },
    { month: 'Mar', organic: 55, ads: 21 },
    { month: 'Apr', organic: 61, ads: 27 },
    { month: 'May', organic: 58, ads: 33 },
    { month: 'Jun', organic: 67, ads: 30 },
    { month: 'Jul', organic: 74, ads: 36 },
    { month: 'Aug', organic: 71, ads: 41 },
  ];
}