Plotly 4.x to 5.x migration: Figure dict schema and layout template compatibility
0 reputation · 28 Jun 2022, 16:58 UTC
0 reputation · 28 Jun 2022, 16:58 UTC
Updating a production application from Plotly 4.x to 5.x introduces changes to the figure dictionary schema, specifically regarding default layout templates and modebar visibility settings. When migrating existing figures that rely on implicit defaults, there is a risk of rendered output shifting visually or losing specific UI elements upon deployment.
To ensure a zero-downtime transition, the application must handle these schema shifts without breaking existing Dash callbacks or altering the end-user experience. This requires a strategy for reconciling the 4.x default state with the 5.x template system.
34275 reputation · 28 Jun 2022, 18:36 UTC
To keep the modebar and layout template rendering identical between Plotly 4.x and 5.x, explicitly set figure.layout.template (e.g., 'plotly' or 'plotly_white') and figure.config.displayModeBar to true (with any desired button removals) before the figure is passed to dcc.Graph. This locks the defaults that otherwise shift in 5.x.
In Plotly 4.x the layout template was optional and visual defaults lived directly in the layout keys (font, colorway, hovermode, etc.). Plotly 5.x makes 'plotly' the implicit default template and moves those defaults into the template system. The modebar also changed its default orientation and button set. If a figure relies on the old implicit defaults, the resolved layout after template merging can differ, causing visible shifts or missing UI elements.
Plotly 5.x validates layout.template and layout.template.data more strictly. Setting template to a known value prevents the library from falling back to its internal defaults. The modebar defaults in 5.x are displayModeBar: true with a vertical orientation; specifying config explicitly freezes the UI across versions. The plotly.io.validate function (or to_json(validate=True)) will raise on deprecated layout keys that should reside inside a template.
Ensure every figure dict has a template:
if 'template' not in fig['layout']:
fig['layout']['template'] = 'plotly' # or 'plotly_white'
Freeze modebar settings:
if 'config' not in fig:
fig['config'] = {'displayModeBar': True, 'displaylogo': False}
# optionally add button removals
fig['config'].setdefault('modeBarButtonsToRemove', ['pan2d', 'lasso2d'])
Move any inline layout overrides (font, colorway, hovermode, etc.) into a custom template object and assign it to layout.template, then strip those keys from the layout root. This mirrors how 5.x merges template.layout over the base layout.
Validate the normalized figure before returning it from a Dash callback:
import plotly.io as pio
pio.to_json(fig, validate=True) # raises if schema drift remains
In a zero‑downtime deployment, wrap the figure‑generation function with the normalizer so both 4.x and 5.x codepaths produce the same dict.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.