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

CSS Grid layout - automatic graph scaling

Dear all,

this question is a follow up to:

I am trying to work with dash and css grid layout. What I would like is to structure a grid in a central place and have all my graphs and tables fill the space in the grid areas. Unfortunately the grid layout does not explicitly set width/height on the different areas. At the same time the dash graphs adapt automatically to the width of the container but the height is fixed by default. Inheriting the height is not possible because the grid elements do not have height set explicitly.

Is there another way to achieve this?

Below a minimal example of what I would like to do.

import dash
import dash_core_components as dcc
import dash_html_components as html

app = dash.Dash(__name__)

graph = dcc.Graph(
        id='example-graph',
        figure={
            'data': [
                {'x': [1, 2, 3], 'y': [4, 1, 2], 'type': 'bar', 'name': 'SF'},
                {'x': [1, 2, 3], 'y': [2, 4, 5], 'type': 'bar', 'name': u'Montral'},
            ],
            'layout': {
                'title': 'Dash Data Visualization'
            },
        },
    style={
         # does not work in this context
        'height': 'inherit',
        # 'width': '90vh',
        # 'height': '50vh'
    }

)


app.layout = html.Div(className='wrapper',
                      children=[
                          html.Div(className='header', children=[]),
                          html.Div(className='leftCol', children=[]),
                          html.Div(className='rightCol', children=[]),
                          html.Div(className='midTop', children=[graph]),
                          html.Div(className='midBottom', children=[]),
                          html.Div(className='footer', children=[]),
                      ])

CSS:

.wrapper {
    display: grid;
    grid-template-columns: 1fr 4fr 4fr 1fr;
    grid-template-rows: 15vh 50vh 20vh 8vh;
    grid-template-areas:
        "header header header header"
        "leftCol midTop midTop rightCol"
        "leftCol midBottom midBottom rightCol"
        "footer footer footer footer";
    grid-gap: 5px;
}

.midTop{
    grid-area: midTop;
    background-color: lightgrey;
}

The specifics of why this works in my case, I don’t really know, but I can say that i made this work by fiddling with how the width and height of both the container and the columns and rows where defined.
I’ve found that if I define the width of the grid container and rows in a percentage and the height of the same in viewWidth then scaling “just works”.

Python layout example:

html.Div(
    id="report-container",
    children=[
        dcc.Graph(
            id="main-graph-container"
        ),
        dcc.Graph(
            id="related-graph"
        ),
        dcc.Graph(
            id="related-graph"
        )
    ]
)

CSS:

#report-container {
    position: relative;
    box-sizing: border-box;
    width: 100%;
    height: 50vw;
    padding: 1%;
    display: grid;
    grid-template-columns: repeat(6, 15.83333%);
    grid-template-rows: repeat(3, 15.3vw);
    gap: 1vw 1%;
}

.main-graph-container {
    grid-row: 1 / 3;
    grid-column: 2 / 5;
}

.related-graph {
    grid-column: 5 / 7;
}

(Yes these calculations are hardcoded by hand - there should be a better way with custom variables if you take the time)

The above breaks as soon as the dcc.Graph components are wrapped in anything. Even dcc.Loading components sadly.

I’m still working on this, so any new insights I find I’ll share.

We’re considering a better solution for more “responsive” dcc.Graphs. You’re welcome to test this draft PR with dcc.Graph(responsive=True, ...):

You can also try setting responsive to True in the config argument of dcc.Graph:

            dcc.Graph
                config={'responsive': True},
                style={'height': '100%', 'width': '100%'}
            )

Inheriting the height is not possible because the grid elements do not have height set explicitly.

It’s true that the grid elements don’t have height defined explicitly in CSS, but they still have real, rendered dimensions. So plotly.js should be using the final “calculated” height regardless. We’ve noticed some bugs with flexbox and grid, which the PR I posted above is also intended to help resolve.