Skip to content

Fix to_html responsive height by styling outer wrapper div#5596

Open
SharadhNaidu wants to merge 1 commit into
plotly:mainfrom
SharadhNaidu:fix-5591-responsive-html-height
Open

Fix to_html responsive height by styling outer wrapper div#5596
SharadhNaidu wants to merge 1 commit into
plotly:mainfrom
SharadhNaidu:fix-5591-responsive-html-height

Conversation

@SharadhNaidu
Copy link
Copy Markdown

Link to issue

Closes #5591

Description of change

to_html wraps the figure inside an outer <div> that has no inline style. The inner figure div sets style="height:100%; width:100%;", but because the wrapper has no height, that 100% resolves to zero, and plotly.js then falls back to its hardcoded 450px default.

The result: the documented default of default_height='100%' cannot inherit from a sized parent container. Any figure placed inside a Jinja template, a Dash container with a vh/% height, or any responsive layout silently renders at 450px instead of filling its parent. This is the underlying cause of #5591 (and the long-standing plotly.js#5270). PR #5590 documented a regex-based workaround; this PR addresses the root cause.

The fix moves the requested default_height/default_width onto the outer wrapper, and changes the inner figure div to height:100%; width:100%; so it fills the wrapper:

- <div>
+ <div style="height:{height}; width:{width};">
          {mathjax_script}
          {load_plotlyjs}
              <div id="{id}" class="plotly-graph-div"
- style="height:{height}; width:{width};"></div>
+ style="height:100%; width:100%;"></div>

Behavior matrix

Caller's intent Before this PR After this PR
Default (height='100%'), figure in container with height:30vh Renders at 450px (collapsed wrapper) Renders at 30vh as expected
Explicit pixel (default_height=400) 400px 400px (unchanged)
Default (height='100%'), no sized parent plotly.js 450px fallback plotly.js 450px fallback (unchanged)
full_html=True standalone page Fills viewport Fills viewport (unchanged)

Pixel defaults and standalone-document use cases are byte-for-byte equivalent in observable layout. The only behavioral change is that percentage defaults now actually inherit from a sized parent, which matches the docstring.

Testing strategy

Two regression tests added in tests/test_io/test_html.py:

  • test_outer_wrapper_carries_requested_dimensions asserts the wrapper div has the percentage style and the inner figure div is set to 100% of it.
  • test_outer_wrapper_respects_explicit_pixel_dimensions asserts pixel defaults flow through unchanged.

Existing test_html_deterministic and the CDN/integrity tests are unaffected because they assert content presence, not the wrapper element.

Notes for review

  • This is a small visible structural change to to_html output. If maintainers prefer to gate it behind an opt-in (e.g. responsive_layout=True), I am happy to refactor - just let me know.
  • I have not been able to reproduce a downstream consumer (Dash, JupyterLab extension, nbconvert) that depends on the wrapper being unstyled. If you know of one, please flag and I will investigate.

Guidelines

The HTML produced by `to_html` wraps the figure in an outer `<div>` with
no inline style. The inner figure div sets `height:100%`, but because
the wrapper has no height, that 100% resolves to zero and plotly.js
falls back to its hardcoded 450px. The result is that the documented
default of `default_height='100%'` cannot inherit from a sized parent
container, so figures embedded in responsive layouts (Jinja templates,
Dash containers with `vh`/`%` heights, etc.) silently render at 450px.

Move the requested dimensions onto the wrapper and let the inner figure
div fill it. Pixel defaults still produce a fixed-size figure; percentage
defaults now propagate from the parent container as the docstring claims.

Closes plotly#5591
@SharadhNaidu SharadhNaidu force-pushed the fix-5591-responsive-html-height branch from d9fef0e to 083b847 Compare May 15, 2026 06:44
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.

[BUG]: Python to_html output disrespects containing HTML vertical height

1 participant