Can't seem to change default Height on Graph

Need help understanding where this should be set and how it depends on container elements.
Can anyone provide a simple example with a proper way to set this where Graph height is not 450px by default?

(i see another post with same problem Callback with one of the Input matching the Output - Automatic graph height - #2 by radekwlsk)
and also some posts about similiar issues under plotly.js topic ( Initial svg height before window resize - #2 by etienne )
that posts mentions lack of default height of parent container.

image

1 Like

That height is set automatically by plotly.js to be the size of the container. There are two ways to set the height:

  1. Set the height of the container of the graph element by passing in style to dcc.Graph, e.g. dcc.Graph(style={'height': '700px'}, id='my-graph', figure={...})
  2. Set the height of the graph itself and let the container expand to that height. This is configured by setting the height of the figure.layout property.

Here is an example of both methods.

import dash
import dash_html_components as html
import dash_core_components as dcc

app = dash.Dash()

app.layout = html.Div([
    dcc.Graph(
        id='graph-1',
        figure={
            'data': [{
                'y': [1, 4, 3]
            }],
            'layout': {
                'height': 800
            }
        }
    ),
    html.Hr(),
    dcc.Graph(
        id='graph-2',
        style={
            'height': 800
        },
        figure={
            'data': [{
                'y': [1, 5, 2]
            }]
        }
    )
])

if __name__ == '__main__':
    app.run_server(debug=True)
9 Likes

Thank you!! Both of those work for me for setting initial height now. I think i had syntax issues (ie ‘800px’. not a valid value) before.
Being able to set this is already so much better then 450 always!

Ideally I would like to let the Graph size itself with the browser window, but still can’t get there!

  1. Is it correct that there is no way so set height or width here as percentage of window area ‘100%’ or ‘50%’. ?

  2. Now the next issue seems to be that regardless of ‘autosize’ layout setting the plot is not resizing the height upon window resize. The width is being resized automatically but not the height. This is an issue only going through Dash. Without Dash the figure is auto-resizing both height and width fine.

As an example: take your code from above and comment out setting height in both Graphs as below and then try to resize the window. On my browser (Chrome on Windows) width changes but height doesn’t. Is it the same behavior for you? Is this the designed behavior or bug?

import dash
import dash_html_components as html
import dash_core_components as dcc

app = dash.Dash()

app.layout = html.Div([
    dcc.Graph(
        id='graph-1',
        figure={
            'data': [{
                'y': [1, 4, 3]
            }],
#            'layout': {
#                'height': 800
#            }
        }
    ),
    html.Hr(),
    dcc.Graph(
        id='graph-2',
#        style={
#            'height': 800
#        },
        figure={
            'data': [{
                'y': [1, 5, 2]
            }]
        }
    )
])

if __name__ == '__main__':
    app.run_server(debug=True)

Try viewport sizing in the parent container like `dcc.Graph(style={‘width’: ‘90vh’, ‘height’: ‘90vh’}). Here’s more on viewport sizing: Fun with Viewport Units | CSS-Tricks - CSS-Tricks

2 Likes

Yes, this is the same for me and this is the desired behaviour. In this case, the height is fixed but the width isn’t. If you want to fix the width, then then you can specify it just like you would the height: width: 600px.

What behaviour were you expecting?

1 Like

Summary of sizing graphs with Dash:

In summary:

  • Setting the size of the container is done with dcc.Graph(style={...}). These are CSS styles, so any units work: %, px, vh, vw. The Graph should expand into the container.
  • The figure of the graph can also have dimensions and these are specified through the layout, figure={'layout': {'width': '100px'}}. Only px are supported here. I don’t think that there are any advantages to setting the dimensions in the figure rather than the container (as in style= as above).
  • When the window resize, the graph is automatically re-plotted inside the container - expanding to the container’s dimensions. Behind-the-scenes, this is happening with the Plotly.resize plotly.js call (here’s the code: https://github.com/plotly/dash-core-components/blob/c898d75a1a189943bcf92bc73b95bd08432ddd7d/src/components/Graph.react.js#L127-L129)
  • Note that if the container itself is resizable, the graph will not be replotted/resized. There isn’t a reliable way to tell if a graph’s container has changed size in JavaScript yet, so we’re just checking if the window is resized.
11 Likes

Thank you Chris! From first try the viewport sizing is doing the trick along the lines of what I was hoping for behavior wise! Now I just have to play around with to get it to the exact layout I want. Didn’t know about it, just starting to learn more about CSS.
Thanks for the thorough explanation of sizing. This is perfect, the flexibility with CSS styling and Plotly Graph components is there and powerful to do a lot of things layout wise. Initially when learning there is some confusion when there are multiple places to do things such as set height/width and subtle differences in limitations or flexiblity of each option. Just have to learn all the tricks to develop best practices!

2 Likes

I’m having the same issue and have been working on it for a week now.
I’ve tried using local static css file, as well as directly using the ‘style’ option to dcc.Graph, which worked.

I’ve recently switched to using a grid construct as my container, everything has defaulted to a height of 450px. If I set my row size to auto, to a fixed pixel size, or a variable size using vh, the plots size to 450 px and get clipped.

Any ideas on how to use a grid and still be able to control graph size, where the graph fits nicely in a grid element?

can you please post small reproducible examples showing what you have tried and what hasn’t worked?

Chris, yes sorry, that is always the first and polite, thing to do. Is there a way to discuss offline? Per company guidelines, I can’t publicly post certain things, unfortunately. That’s why I waited a week to send a message.

Right now, we only do 1-1 private support for companies or organizations that have a (paid) support plan (Consulting, Training & Open-Source Development) - it’s really the only way that we can scale helping out such a large community.

Is it possible for you to remove sensitive data and post dummy examples? For example, something like:

app.layout = html.Div([
    dcc.Graph(id='attempt-1', figure={
        'data': [{'x': [1, 2, 3]}],
        'layout': {'height': 600}
    }),

    html.Div(
        dcc.Graph(id='attempt-2', figure={
            'data': [{'x': [1, 2, 3]}],
        }),
        style={'height': 600}
    ),

    html.Div(
        dcc.Graph(id='attempt-3', figure={
            'data': [{'x': [1, 2, 3]}],
        }),
        style={'height': '60vh'}
    )
])

Chris,
I just saw your response, but anticipated as much. So I put together an example, and it illustrates what’s happening, I’m sure my misunderstanding.

When I was a kid I moved to Montreal in 1986. So I made a toy example that has the goals, assists, points, and shot stats for the top 13 point leaders of the Habs that year. Mats Naslund led the team.

What is happening is the difference in syntax between

  1. html.Div([ put something here], add style here ) and
  2. html.Div(put something here, add style here)

I assumed that ‘[’ was just a shorthand to denote child elements of the parent div. Below you can see, that the second plot honors my plot setting in ‘vh’, and ‘vw’, but the top plot does not. When I use syntax 1, the ‘svg-container’ defaults to a height of 450 px, and my style settings for the plot aren’t honored.

The reason I want to use syntax 2, is that I want to add an individual style to dropdowns, but currently I get an error when I try.

import dash
import dash_core_components as dcc
import dash_html_components as html
import plotly.graph_objs as go
import pandas as pd

stats= {
    'Goals': [43,32,19,32,20,15,20,19,19,21,19,8,14], 
    'Assists': [67, 55, 63, 39, 36, 34, 23, 21, 20, 16, 15, 26, 17],
    'Points' : [110, 86, 82, 71, 56, 49, 43, 40, 39, 37, 34, 34, 31],
    'Shots' : [223, 202, 167, 172, 147, 115, 135, 103, 119, 112, 120, 101, 102]
    }
df = pd.DataFrame(stats)

#button options
options = [{'label': str(i), 'value':str(i)} for i in ['Goals','Assists','Points','Shots']]

#grid layout
container= {
    'display':'grid',
    'grid-template-columns':'repeat(2, 1fr)',
    'grid-template-rows':'repeat(2, minmax(100px, auto))',
    'grid-padding': '1em',
}

#placeholder layout
placeholder = {
    'background': "#eee",
    'border-style':'solid',
    'border-size':'0.5em',
    'border-color':'#ddd'
}

app = dash.Dash('')
app.css.config.serve_locally = True
app.scripts.config.serve_locally = True

app.layout = html.Div([
    # grid 1,1
    html.Div([
        html.Div(
                dcc.Dropdown(
                    id='category',
                    options= options,
                    value= 'Goals'
                    ),
                ),
        html.Div([
                dcc.Graph( 
                    id = 'histogram' )
                ], style={'height':'60vh', 'width':'55vw'})
        ]),
        # grid 1,2
        html.Div('placeholder', style=placeholder)
        ,
    #grid 2,1
    html.Div([
        html.Div([
                #feature dropdown
                dcc.Dropdown(
                    id='xvalue',
                    options=options,
                    value ='goals'
                    ),
                dcc.Dropdown(
                    id='yvalue',
                    options=options,
                    value='goals'
                    ),
                ]),
        html.Div( 
            dcc.Graph( id ='scatter' ,  style={'height':'60vh', 'width':'55vw'})
            )
        ]),
    #grid 2,2
    html.Div(
        'placeholder',  style=placeholder )            
    ], style=container )

#histogram callback
@app.callback(
    dash.dependencies.Output('histogram', 'figure'),
    [dash.dependencies.Input('category', 'value')]
)
def update_histogram(value):
    return {
        'data':[ 
           go.Histogram(
            x=df[value]
            )],
        'layout':go.Layout()
            }
         

@app.callback(
    dash.dependencies.Output('scatter', 'figure'),
    [dash.dependencies.Input('xvalue', 'value'),
    dash.dependencies.Input('yvalue', 'value')]
)
def update_scatter(xvalue,yvalue):
    return { 
        'data': [
             go.Scatter(
                x=df[xvalue],
                y=df[yvalue],
                mode='markers'
            )
         ] ,
    'layout' : go.Layout( )
    }
2 Likes

Best community example ever, love this! :canada:

Thanks for the example! I think that the issue isn’t actually the [] syntax, but rather that the plotly.js chart looks to the immediate parent container for style information and isn’t reading a parent’s inherited height for some reason - this looks like a bug.

It looks like you found a way around this in the second row: You can set the height of the Graph’s parent’s Div (see source code here: dash-core-components/src/components/Graph.react.js at master · plotly/dash-core-components · GitHub) by passing in style= to the Graph component.

So, this will work:

html.Div([
    dcc.Dropdown(),
    dcc.Graph(style={'height': '60vh'})
])

But this won’t necessarily work:

html.Div(style={'height': '60vh'}, children=[
    dcc.Dropdown(),
    dcc.Graph()
])

and this won’t work either

html.Div([
    dcc.Dropdown(),
    html.Div(dcc.Graph(), style={'height': '60vh'})
])

I’ll open an issue in the plotly.js repo (GitHub - plotly/plotly.js: Open-source JavaScript charting library behind Plotly and Dash) and then I’ll report back

4 Likes

Thanks Chris,
Your explanation makes sense.

The reason I resorted to using ‘style’ as an explicit inline dictionary in the graph’s div, was because my attempts set the graph’s properties using a stand-alone, offline CSS stylesheet kept failing.

I was using the the method off styling graphs using an offline CSS, as you recommended here:

I found that when I used the offline CSS, my plot’s height style wasn’t being inherited. I was using the syntax:

html.Div([
dcc.Dropdown(),
html.Div(dcc.Graph(),className=“class in style sheet”)
])

Your explanation seems to encompass that use case. I’ll go back and see if this was a manifestation of the same bug. Every time used the browser’s inspection tool I could see that my plot height was never inherited.

The big unknown to me at the time, was if the behavior was due:

  1. The fact that I’m new to plotly, and was perhaps just using it incorrectly, or
  2. a bug

Thanks again

1 Like

Oops, I thought I had deleted those lines after ‘Thanks again’. Please ignore them

I used the following:

    html.Div([
        dcc.Graph(id='ts1', style={"height": "100vh", "width": "25vw","float": "left", 'display': 'inline-block'}),
        dcc.Graph(id='ts2', style={"height": "100vh", "width": "25vw","float": "left", 'display': 'inline-block'}),

        dcc.Graph(id='ts3', style={"height": "100vh", "width": "25vw", "float": "left", 'display': 'inline-block'}),
        dcc.Graph(id='ts4', style={"height": "100vh", "width": "25vw", "float": "left", 'display': 'inline-block'}),

    ], style={"height" : "97vh", "width" : "100vw"}),

but the graphs overlap on top of each other. Parts of the graph gets cut off.

It seems that I cant set the height and width of the svg-container even though I am adding style directly to dcc.Graph.

What am I missing?

1 Like

Chris,
Was wondering if there was any update this? Thanks,
Mike

@makn87 - Besides the vh issue, were there any other bugs or questions?

This issue is in here: Make layout height & width understand viewport and percentage sizes · Issue #106 · plotly/plotly.js · GitHub

We left off with

I believe that we solved this by passing in style directly into dcc.Graph. Is there anything else?