Black Lives Matter. Please consider donating to Black Girls Code today.

Using templates in Plotly v4: works in JupyterLab not not when exported to HTML

I’m currently creating some offline Plotly (v4) plots in JupyterLab and they show up in the notebook but show as blank when exported to HTML. I’ve traced the issue back to the use of a custom template. Below are two minimum working examples: the first demonstrates the problem when using a custom template, while the second functions once the custom template is removed. My thought is that nbconvert isn’t properly embedding the relevant non-default template information, but I’ve haven’t been able to trace down the specifics. Thoughts?

Exported HTML shows blank space where the figure should be

import plotly.graph_objects as go

# Define the default tick formatting
tickformatting = {'ticks': "outside",
                  'tickfont': {'size': 18},
                  'showticksuffix': 'all',
                  'showtickprefix': 'last',
                  'showline': True
                  }

# Create a default template for the plotly plots
template = go.layout.Template(
    layout=go.Layout(title_font={'color': '#7f7f7f', 'family': 'Sans-serif', 'size': 24},
                     font={'color': '#7f7f7f', 'family': 'Sans-serif', 'size': 18},
                     xaxis=dict(**tickformatting),
                     yaxis=dict(**tickformatting),
                     margin={"l": 150, "r": 150})
)


    
fig = go.Figure()
fig.update_layout(title="Figure Title",
                  template=template)
fig.show()

Exported HTML shows figure

import plotly.graph_objects as go

# Define the default tick formatting
tickformatting = {'ticks': "outside",
                  'tickfont': {'size': 18},
                  'showticksuffix': 'all',
                  'showtickprefix': 'last',
                  'showline': True
                  }

# Create a default template for the plotly plots
template = go.layout.Template(
    layout=go.Layout(title_font={'color': '#7f7f7f', 'family': 'Sans-serif', 'size': 24},
                     font={'color': '#7f7f7f', 'family': 'Sans-serif', 'size': 18},
                     xaxis=dict(**tickformatting),
                     yaxis=dict(**tickformatting),
                     margin={"l": 150, "r": 150})
)


    
fig = go.Figure()
fig.update_layout(title="Figure Title")
fig.show()

I finally figured out the issue. I can’t say I fully understand the details, but it primarily has to do with plotly renderers and how they are supported in Jupyter. It appears that the functioning example in the previous post (i.e., the one that doesn’t use the template) defaults to using the “notebook” renderer, which directly embeds the plotly js into the html; whereas, the non-functioning example in the previous post (i.e., the one that uses the template) seems to default to the plotly_mimetype renderer. To fix the issue, I simply added the following lines into my code:

import plotly.io as pio

pio.renderers.default = "notebook+plotly_mimetype"

This forces plotly to support both the embeded notebook functionality and the JuupyterLab preferred mimetype functionality. So, when I export the file to HTML, I am able to see the embedded plotly plots. See https://plot.ly/python/renderers/ for more details on renderers.

Final working code:

import plotly.graph_objects as go
import plotly.io as pio

pio.renderers.default = "notebook+plotly_mimetype"

# Define the default tick formatting
tickformatting = {'ticks': "outside",
                  'tickfont': {'size': 18},
                  'showticksuffix': 'all',
                  'showtickprefix': 'last',
                  'showline': True
                  }

# Create a default template for the plotly plots
template = go.layout.Template(
    layout=go.Layout(title_font={'color': '#7f7f7f', 'family': 'Sans-serif', 'size': 24},
                     font={'color': '#7f7f7f', 'family': 'Sans-serif', 'size': 18},
                     xaxis=dict(**tickformatting),
                     yaxis=dict(**tickformatting),
                     margin={"l": 150, "r": 150})
)


    
fig = go.Figure()
fig.update_layout(title="Figure Title",
                  template=template)
fig.show()