How to Format ECharts Tooltips with Custom HTML Templates
ECharts formats tooltips through a formatter option that accepts string templates with placeholders ({a}, {b}, {c}), synchronous functions returning HTML strings, or asynchronous functions using a callback parameter, with content rendered via createTooltipMarkup in src/component/tooltip/tooltipMarkup.ts and automatically HTML-encoded via encodeHTML to prevent XSS.
ECharts provides flexible tooltip customization through its formatter option, allowing developers to inject custom HTML templates into chart tooltips. According to the apache/echarts source code, the tooltip markup engine processes these formatters through a secure pipeline that converts templates into either DOM elements or canvas-rich text. Understanding how buildTooltipMarkup and TooltipMarkupStyleCreator interact with your custom HTML ensures you can create rich, interactive tooltips without compromising security.
The Formatter API
The tooltip.formatter option supports three distinct patterns for generating content:
- String template: Static HTML containing placeholders like
{a}(series name),{b}(data name),{c}(value), and{d}(percent). - Function: JavaScript function receiving data parameters and returning an HTML string.
- Asynchronous function: Function receiving a
callbackparameter to resolve content after async operations.
All formatter types ultimately pass through createTooltipMarkup in src/component/tooltip/tooltipMarkup.ts, which builds a markup tree before rendering.
String Template Formatters
String templates provide the simplest approach for basic HTML formatting. The template engine replaces placeholders with actual data values before passing the result through the markup builder.
option = {
tooltip: {
trigger: 'axis',
formatter: `
<div style="font-weight:bold;">{a}</div>
<div>{b} : {c} ({d}%)</div>
`
},
xAxis: { type: 'category', data: ['Mon', 'Tue', 'Wed'] },
yAxis: { type: 'value' },
series: [{
type: 'bar',
name: 'Sales',
data: [120, 200, 150]
}]
};
In src/component/tooltip/tooltipMarkup.ts (lines 72–78), the string is processed by buildSection and automatically HTML-encoded via encodeHTML to prevent injection attacks while preserving your template structure.
Function-Based Formatters
For dynamic content requiring calculations or conditional logic, use a function formatter defined in src/component/tooltip/TooltipModel.ts (lines 35–38).
Synchronous Functions
The function receives a params object (or array for axis triggers) containing seriesName, name, value, and other metadata:
option = {
tooltip: {
trigger: 'item',
formatter: function (params) {
return `
<div style="color:#fff;background:#333;padding:5px;">
<strong>${params.seriesName}</strong><br/>
${params.name}: <em>${params.value}</em>
</div>`;
}
},
series: [{
type: 'pie',
data: [
{value: 335, name: 'A'},
{value: 123, name: 'B'}
]
}]
};
Asynchronous Functions with Callback
For data fetched from APIs, the formatter accepts a third callback parameter. The implementation in test/tooltip.html (lines 998–1013) demonstrates this pattern:
option = {
tooltip: {
trigger: 'axis',
formatter: function (params, ticket, callback) {
setTimeout(function () {
const html = `
<div>Fetched at ${new Date().toLocaleTimeString()}</div>
<div>Sum: ${params.reduce((s, p) => s + p.value, 0)}</div>`;
callback(ticket, html);
}, 800);
return 'loading…';
}
},
series: [{ type: 'line', data: [10, 20, 30] }]
};
The callback(ticket, html) resolves the tooltip content while the initial return value displays temporary loading text.
Render Modes and Security
ECharts supports two rendering paths that affect how your HTML template becomes visual output.
HTML Mode and XSS Protection
When renderMode is 'html' (default), the tooltip renders as a DOM element. The encodeHTML function in src/component/tooltip/tooltipMarkup.ts (lines 72–78) escapes all user-provided placeholder values before insertion, preventing XSS attacks while allowing your literal HTML markup to function normally.
RichText Mode for Canvas/SVG
For canvas-based charts without DOM overlay, set renderMode: 'richText'. In this mode, TooltipMarkupStyleCreator (lines 150–180 in tooltipMarkup.ts) converts your formatter output into styled text fragments rather than HTML elements:
option = {
tooltip: {
renderMode: 'richText',
formatter: '{a}<br/>{b}: {c}'
},
series: [{ type: 'scatter', data: [[10, 20], [15, 25]] }]
};
Both modes share the same formatter syntax, but buildTooltipMarkup generates different internal representations depending on the render target.
Key Implementation Files
Understanding the ECharts tooltip architecture requires familiarity with these specific files:
src/component/tooltip/TooltipModel.ts: Defines thetooltipoption schema, includingformatterandrenderModedefaults (lines 35–38).src/component/tooltip/tooltipMarkup.ts: Core markup engine containingcreateTooltipMarkup,buildTooltipMarkup,encodeHTML, andTooltipMarkupStyleCreator(lines 27–33, 72–78, 150–180).test/tooltip.html: Live demonstration of async formatters and edge cases (lines 998–1013).
Summary
- String templates use placeholders (
{a},{b},{c}) for simple HTML formatting without JavaScript logic. - Function formatters provide full control via
paramsobjects and return literal HTML strings. - Async formatters utilize the
callback(ticket, html)pattern demonstrated intest/tooltip.htmlfor deferred content loading. - HTML mode automatically encodes placeholder values via
encodeHTMLintooltipMarkup.tsto prevent XSS. - RichText mode converts output through
TooltipMarkupStyleCreatorfor canvas/SVG rendering without DOM elements.
Frequently Asked Questions
How do I access the series color in a custom tooltip formatter?
The params object passed to function formatters includes a color property containing the item's assigned color. Access it via params.color to style markers or borders in your HTML template.
Can I use JavaScript event listeners in tooltip HTML?
Yes, but only when renderMode is set to 'html'. The resulting DOM element supports standard HTML including button and anchor tags with event handlers. Avoid inline event attributes in favor of delegated events due to the tooltip's dynamic DOM insertion.
Why is my HTML showing as plain text instead of rendering?
Verify that renderMode is not set to 'richText', which converts HTML tags to literal text rather than DOM elements. Also ensure your tooltip.formatter returns a string, not a DOM node, as ECharts handles the insertion internally.
What is the performance impact of async tooltip formatters?
Async formatters trigger DOM updates via callback, which causes tooltip repositioning after content loads. For high-frequency charts with real-time data, async tooltips may cause flickering or layout shifts; consider pre-fetching data or using synchronous formatters with cached values instead.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →