Skip to content

demo(chart): Demonstrate text bounds measurement inconsistencies#2800

Draft
awahab07 wants to merge 1 commit into
elastic:mainfrom
awahab07:TEST-canvas-ctx-measureText-quirks
Draft

demo(chart): Demonstrate text bounds measurement inconsistencies#2800
awahab07 wants to merge 1 commit into
elastic:mainfrom
awahab07:TEST-canvas-ctx-measureText-quirks

Conversation

@awahab07
Copy link
Copy Markdown
Collaborator

@awahab07 awahab07 commented Mar 4, 2026

Summary

Draft / demonstration only — not intended to merge.

Adds a storybook story to demonstrate how canvas-based measureText() fails to account for inherited CSS font properties (font-feature-settings, font-variant-numeric, letter-spacing, font-kerning), leading to incorrect text layout across multiple chart types.

image

Details

Problem

All chart types use an off-screen canvas (document.createElement('canvas')) for text measurement. This canvas is detached from the DOM, so it cannot inherit CSS font properties from parent elements. When properties like font-feature-settings: 'tnum' or letter-spacing are applied by the consuming app (e.g. Kibana/Lens), measureText() still reports the non-featured width — causing a measurement-vs-rendering mismatch.

Why this can't be fixed via ctx.font: The Canvas 2D ctx.font only accepts CSS font shorthand, which does not include font-feature-settings, font-variant-numeric, letter-spacing, or font-kerning. The CanvasTextDrawingStyles interface does expose letterSpacing, fontKerning, and wordSpacing — but elastic-charts does not currently use them, and fontFeatureSettings / fontVariantNumeric have no canvas API equivalent at all.

What the story demonstrates

The story (Test Cases → Font Measurement Test) includes 4 individually resizable charts with toggleable OpenType font features, letter-spacing, and font-kerning:

Chart Measurement used for Visible issue when measurement is wrong
Metric Responsive font size selection Value text clips or overflows
Bar + Legend Axis space, display value overflow, legend width Tick labels overlap, legend truncates prematurely
Treemap Label fitting inside cells Labels overflow cell boundaries
Heatmap Cell label maximiseFontSize(), Y-axis width Cell values clip, axis labels overlap

Key observations

  • DOM ↔ Canvas mismatch is the most impactful scenario: Metric, Bullet (metric mode), and Legend render text as DOM elements but compute layout using canvas measureText(). The DOM text inherits all CSS properties; the measurement does not.
  • letter-spacing and font-kerning are completely absent from the measurement code — not accounted for at all, regardless of whether the canvas is in-DOM or off-screen.

Browser quirks

  • Chrome: An in-DOM canvas appears to inherit font-feature-settings from ancestor CSS and apply it during measureText() and fillText(), but this behavior is not guaranteed by the spec and is inconsistent even within Chrome (e.g. treemap renders with tnum applied, but heatmap does not, despite both using the same in-DOM canvas with identical computed styles).
  • Firefox: Does not appear to inherit font-feature-settings into canvas text shaping at all — measureText() and fillText() ignore the canvas element's computed font-feature-settings, even when directly set as an inline style on the element.
  • Spec ambiguity: The WHATWG spec says ctx.font values are "computed relative to the font of the canvas element", but does not explicitly state whether non-shorthand properties like font-feature-settings should participate in canvas text shaping.

How to test

  1. Open Test Cases → Font Measurement Test in the deployed storybook
  2. Toggle font feature knobs (all ON by default) and adjust letter-spacing / font-kerning
  3. Resize individual charts to observe how the mismatch scales
  4. Compare Chrome vs Firefox

Issues

Related to Kibana/Lens OpenType font feature adoption (elastic/kibana#251576).

Checklist

  • The proper documentation and/or storybook story has been added or updated

@awahab07 awahab07 changed the title demo(chart): Text bounds measurement inconsistencies demo(chart): Demonstrate text bounds measurement inconsistencies Mar 4, 2026
@elastic-datavis
Copy link
Copy Markdown
Contributor

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant