Tick labels
categoryAxis.tickLabel controls the text drawn at each tick of the category axis: how it reads (format), which way it faces (rotation, anchor) and what happens when the labels need more room than the axis has. There are two ways out of that: cut the labels short, or draw fewer of them. Which one the axis takes depends on truncation.enabled and on whether the labels run along the axis or across it.
Value axes take the same tickLabel settings apart from the truncation ones (see valueAxes.tickLabel).
ts
// Long team names on a horizontal category axis. Rotating the labels -45°
// makes them perpendicular to the axis, so each one is truncated to a
// fraction of the plot height (truncation.maxFraction) rather than to the
// width of its category slot; truncation.minLength keeps a readable minimum
// when the chart is short.
import type { MochartInputConfig } from '@mochart/core';
export const config: MochartInputConfig = {
version: '1.0.0',
title: { text: 'Open Tickets by Team' },
categoryAxis: {
property: 'team',
type: 'string',
scale: 'ordinal',
title: { text: 'Team' },
tickLabel: {
rotation: -45,
truncation: { enabled: true, maxFraction: 0.35, minLength: 72, text: '…' }
}
},
valueAxes: [{ id: 'VA0', title: { text: 'Open tickets' }, min: 0 }],
series: [{ property: 'open', title: 'Open tickets', renderer: 'bar' }]
};
export const data = [
{ team: 'Customer Support (Americas)', open: 42 },
{ team: 'Customer Support (EMEA)', open: 37 },
{ team: 'Platform Engineering', open: 18 },
{ team: 'Mobile Applications', open: 25 },
{ team: 'Data and Analytics', open: 11 },
{ team: 'Billing and Payments', open: 29 },
{ team: 'Security Operations', open: 8 },
{ team: 'Developer Relations', open: 14 },
{ team: 'Quality Assurance', open: 21 }
];How it works
rotationturns each label by -90° to 90°. On a horizontal axis the labels count as perpendicular to the axis once the rotation reaches 20° either way; on a vertical axis (a horizontal bar chart) flat labels are already perpendicular, and only a rotation past 70° lays them along the axis. Perpendicular labels take up their text height along the axis instead of their width, so more ticks fit.truncation.enableddefaults totrueon astringaxis andfalseonnumberanddateaxes. When it is on, a label that does not fit is cut andtruncation.textis appended. The room a label gets depends on its direction: a label running along the axis is clipped to the width of its category slot, so every category keeps a label; a perpendicular label may occupy up totruncation.maxFractionof the plot bounds (the plot height for a horizontal axis, its width for a vertical one), and never less thantruncation.minLengthpixels — that floor is what keeps the labels above legible on a short chart.truncation.tooltipEnabled(on by default) gives each truncated label an svg<title>holding its full text, which browsers show as their native tooltip while a mouse or pen rests on the label. Touch has no hover, so nothing shows there; screen readers already get the full text througharia-label.- With truncation off, nothing is cut: the axis drops ticks until the remaining labels fit, as in the next example.
anchorsets which end of the text sits on the tick. The defaultautocentres labels that run along the axis and, for perpendicular ones, anchors the end nearest the axis — a-45°label ends at its tick and reads up towards it, a45°one starts there and reads away. Setstart,middleorendto override.formatis a d3-format string fornumberaxes or a d3-time-format one fordateaxes;autoderives a format from the data andnullshows the raw value.sizeis the space reserved for the labels across the axis,automeasuring the rotated text. A fixed number keeps the plot the same height as the labels change.textStylestyles the text in itsnormal,focusedanddefocusedstates; the defaultcurrentColorfill follows the host page's colour.- The
marginInner/paddingInnerpair spaces the labels from the plot side of the axis, andmarginOuter/paddingOuterfrom the title side. Padding sits inside the label'sbackgroundStylebox, margin outside it.
Fewer ticks instead
When the labels are not truncated, the axis decides how many ticks it can show and hides the rest at a regular interval, so the labels that remain are drawn in full.
ts
// Thirty daily readings on an ordinal date axis. The labels stay flat and
// truncation is off, so the axis keeps only as many ticks as fit — one label
// width plus minTickSpacing per tick, at most maxTickCount — and draws the
// surviving labels in full. format sets the label text.
import type { MochartInputConfig } from '@mochart/core';
export const config: MochartInputConfig = {
version: '1.0.0',
title: { text: 'Daily Visits' },
categoryAxis: {
property: 'day',
type: 'date',
scale: 'ordinal',
title: { text: 'June 2026' },
minTickSpacing: 24,
maxTickCount: 8,
tickLabel: {
format: '%b %d',
truncation: { enabled: false },
marginInner: 4,
textStyle: { normal: { fillOpacity: 0.75 } }
}
},
valueAxes: [{ id: 'VA0', title: { text: 'Visits' }, min: 0 }],
series: [{ property: 'visits', title: 'Visits', renderer: 'area' }]
};
const firstDay = Date.UTC(2026, 5, 1);
const dayMs = 24 * 60 * 60 * 1000;
export const data = Array.from({ length: 30 }, (_, i) => ({
day: new Date(firstDay + i * dayMs).toISOString(),
// a weekly rhythm: weekends (June 2026 starts on a Monday) dip
visits: Math.round(180 + 40 * Math.sin(i / 2.5) - (i % 7 >= 5 ? 60 : 0))
}));tickCountdefaults toauto: the axis divides its length by one label's extent along it (the widest label's width when flat, the text height when perpendicular) plusminTickSpacing, and keeps that many ticks. On an ordinal axis it keeps every nth category to get down to the count; on a linear axis it asks the scale for that many ticks. A number replaces the calculation outright.maxTickCountcaps the computed count — 10 on a linear axis, uncapped (0) on an ordinal one — so the eight ticks above are the cap, not the fit. On a linear axisminTickIntervalalso stops ticks landing closer together than a given value.- Rotation and truncation fit into the same count: a
stringaxis with truncation on works out the count from the shortest label truncation can produce, which is why it keeps every category, and a rotated axis fits more ticks because each takes less room along the axis.