Excessive margins in graphs (how to remove?)

I am new to dash, though not python (coming from R shiny). Plotly express, by default, creates a substantial horizontal and vertical margin around a plot (within the SVG render region), on the order of 125px on the top and 125px on the left hand side. How do I get rid of it?

I assume the margin on top is there for the toolbar + title. However I have disabled both with:

dcc.Graph(id='graph1', config={ 'displayModeBar': False})

...
fig = px.line (df, x='date', y=['strategy', 'spy'], labels=None)
fig.update_layout(
    legend=dict(
        yanchor="top",
        y=0.99,
        xanchor="left",
        x=0.01,
        bgcolor=None
    )
)

fig.update_xaxes(title=None)
fig.update_yaxes(title=None)

The graph area (which I checked with browser element inspection) has ~125px of wasted space on the top and left. I would like the graph to occupy the full SVG viewport and be flush with the title “Graph” above:

Here is all of the test code for reference:

import pandas as pd
import numpy as np
import dash
import plotly.express as px
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
import dash_bootstrap_components as dbc

app = dash.Dash(__name__, external_stylesheets = [dbc.themes.UNITED])

#
# Structure
#

def Navbar():
    navbar = dbc.NavbarSimple(
        children=[
            dbc.NavItem(dbc.NavLink("Summary", href="/summary")),
            dbc.NavItem(dbc.NavLink("Detail", href="/detail")),
        ],
        brand="CMV Strategy",
        brand_href="/summary",
        sticky="top",
        color='secondary'
    )
    return navbar

def summary():
    text = """\
        Donec id elit non mi porta gravida at eget metus.Fusce dapibus, tellus ac cursus commodo, 
        tortor mauris condimentumnibh, ut fermentum massa justo sit amet risus. Etiam porta semmalesuada 
        magna mollis euismod. Donec sed odio dui. Donec id elit nonmi porta gravida at eget metus. Fusce 
        dapibus, tellus ac cursuscommodo, tortor mauris condimentum nibh, ut fermentum massa justo sitamet 
        risus. Etiam porta sem malesuada magna mollis euismod. Donec sedodio dui."""

    body = dbc.Container([
        dbc.Row([
            dbc.Col([
                html.H2("Heading"),
                html.P(text),
                dbc.Button("View details", color="secondary")
            ], md=4),
            dbc.Col([
                dbc.Row([
                    html.H2("Graph"),
                    dbc.Col([dcc.Dropdown(id="tenor1", options = [
                        {'label': '1 week', 'value': '1W' },
                        {'label': '1 month', 'value': '1M'},
                        {'label': '3 months', 'value': '3M'},
                        {'label': '6 months', 'value': '6M'},
                        {'label': '1 year', 'value': '1Y'},
                        {'label': 'inception', 'value': '*'},
                    ], value='*', style={"margin-left": "10px"})], width=3)
                ]),
                dcc.Graph(id='graph1', config={
                    'displayModeBar': False
                })
            ]),
        ])
    ], className="mt-4")

    nav = Navbar()
    layout = html.Div([nav, body])
    return layout


def detail():
    pass

#
# Callbacks
#

@app.callback(Output('page-content', 'children'), [Input('url', 'pathname')])
def display_page(pathname):
    if pathname == '/summary' or pathname == "/":
        return summary()
    else:
        return detail()

@app.callback(Output('graph1','figure'), [Input("tenor1", "value")])
def update_graph(value):
    Tbase = pd.to_datetime("2010-1-1")
    dates = [Tbase + pd.DateOffset(days=10*i) for i in range(0,230)]
    s1 = pd.Series(np.random.normal(0.2, 1.0, 230)).cumsum()
    s2 = pd.Series(np.random.normal(0.0, 1.0, 230)).cumsum()
    df = pd.DataFrame({'date': dates, 'strategy': s1, 'spy': s2})

    fig = px.line (df, x='date', y=['strategy', 'spy'], labels=None)
    fig.update_layout(
        legend=dict(
            yanchor="top",
            y=0.99,
            xanchor="left",
            x=0.01,
            bgcolor=None
        )
    )
    fig.update_xaxes(title=None)
    fig.update_yaxes(title=None)

    return fig

app.layout = html.Div([
    dcc.Location(id = 'url', refresh = False),
    html.Div(id = 'page-content')
])

if __name__ == "__main__":
    app.run_server()
1 Like

Documentation is not great. But I found that someone had posted about plotly graph margins. Answer is that can be set as follows:

fig.update_layout(
    margin=dict(l=20, r=20, t=20, b=20),
)
6 Likes

Not sure why, but it gives me an error which tells me that dict not callable is.

*in *
22 # Add figure title

  • 23 fig.update_layout(title_text=“Crossbow & correctierol”, height=800, width=800, *
    —> 24 margin=dict(
  •   25 l =50,*
    
  •   26 r =50,*
    

TypeError : ‘dict’ object is not callable

any clue how to fix this?

It means you used the keyword ‘dict’ as a variable somewhere in your code which should not be.