fix: ResizeObserver based container sizing - #9892
Conversation
|
Heads up — the Vega side of this is being reworked, and it changes what this PR should emit. vega/vega#4318 is being rebuilt around a first-class {"on": [{"events": "container:resize", "update": "containerSize()[0]"}]}Once that lands, the Worth keeping One note on the docs change: "In browsers where Vega uses Thanks for pushing on this — #9349 has been open since 2024 and the container-sizing story is better for it. |
view.resize() touches the autosize signal but never re-evaluates the containerSize()-derived width/height signals, so the autosize handler was a workaround that also required calling view.resize() by hand. Vega's container event source (vega/vega#4318) reports the container's actual size changes, so subscribe to that instead. window:resize is kept for Vega versions that predate the container event source, where an unrecognised event source is silently dropped. Requires the Vega release that ships vega/vega#4318; the runtime test fails until then. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Deploying vega-lite with
|
| Latest commit: |
8e6287f
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://435d5d0a.vega-lite.pages.dev |
| Branch Preview URL: | https://yuvvan-resizeobserver-contai.vega-lite.pages.dev |
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Adds a `container` event source, so a spec can react to its container
changing size the same way it reacts to a window resize:
```json
{"name": "width", "update": "containerSize()[0]",
"on": [{"events": "container:resize", "update": "containerSize()[0]"}]}
```
`containerSize()` was previously only re-read on `window:resize`, which
misses every layout-driven change — a sidebar opening, a flex reflow, a
notebook cell, a resizable panel. That gap is why `"width": "container"`
has been unreliable and why the documented workaround was to fire a
synthetic window resize by hand.
A `ResizeObserver` is attached only when a spec subscribes to the
source, so nothing is observed otherwise. Notifications coalesce to one
dispatch per animation frame, and the observer is suppressed while the
view is running its own resize.
Refs vega/vega-lite#9349
## Layout shift: canvas and SVG roots no longer sit on the text baseline
Both renderers now set `vertical-align: bottom` on the root element.
**This changes the height of every rendered chart by ~6px, whether or
not the spec uses the new event source.**
An inline element sits on the text baseline, so its container reserves
room for the descender below it. That phantom ~6px was measured
identically for canvas (both CSS-sized and attribute-sized) and for SVG.
It disappears with `vertical-align: bottom`, `top`, or `middle`, and
with `display: block`.
`vertical-align: bottom` was chosen over `display: block` because it
preserves inline flow — a small chart in running text stays on its line
rather than moving to its own.
Why it belongs with this feature rather than in a separate PR: without
it, an auto-height container with `"height": "container"` is
unsatisfiable. The container's height is the chart's height plus 6px,
the chart reads that back, and it grows by 6px per render forever. The
feature would ship broken by default for that case, caught only by the
loop guard.
What to expect:
- Every embedded chart becomes ~6px shorter. Usually desirable — it is
space nothing was drawing into.
- Downstream image-comparison baselines will shift. Vega's own goldens
are unaffected (scenegraph and SVG strings, not DOM layout — 693/693
unchanged), but vega-embed, Vega-Lite and Altair screenshot tests will
need regenerating.
- A chart placed inline in running text aligns to the bottom of the line
box rather than the baseline, moving ~3–4px relative to surrounding
text.
- It is an inline style, so a stylesheet overriding `vertical-align` on
`.marks` now needs `!important`.
- Exported SVG is unaffected: `svg()` strips the style attribute before
serializing. That also fixes a latent bug where the export path restored
only `background-color` after clearing the attribute.
## Loop guard
A container whose size is genuinely determined by the view inside it has
no fixed point. After several consecutive rounds where the size sits
exactly where the previous render left it — which nothing external can
produce — the view stops matching and warns once:
> Container size depends on the view it contains; no longer resizing to
match it.
The warning is at `Warn` level, so it is invisible at Vega's default log
level of `Error`.
## Vega-Lite
vega/vega-lite#9892 emits `container:resize` alongside `window:resize`.
Both are kept until Vega-Lite's Vega peer dependency reaches the release
containing this source: on older runtimes an unknown event source
resolves to an empty selector match and silently does nothing, so
dropping `window:resize` early would remove resize behaviour without
warning.
---------
Co-authored-by: Dominik Moritz <domoritz@gmail.com>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
PR Description
Fixes #9349
Refs: vega/vega#4318
Checklist
npm testruns successfullysite/docs/+ examples.Tips: