How to span full height that left in vertical dbc.col space with dash bootstrap dbc.row?

Hello! Recently I started to learn Dash and its a really great project! Thank you for you work!
For now I am trying to build an adaptive app with Dash Bootstrap which consists of two columns - left one is a menu, right one is a content column for tables and plots. Within the second column there is a row block to format content position. For one of the content pages I would like to make a container with adaptive height for cytocsape tree graph. Initially I took dbc.Row object to create it and paste graph as a child. But I cant figure out how to tweak CSS or HTML structure to allow this container span full height left in the content column? Here is a code recreation:

import dash
import dash_bootstrap_components as dbc
from dash import html

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

graph_container = dbc.Row(
    class_name='g-0',
    style={
        'min-height': '100%',
        'background-color':'white'
        }
)

content = dbc.Row(
    [
        dbc.Col(
            [
                html.P('This is column for content'),
                html.P('Sample text 1'),
                html.P('Sample text 2'),
                graph_container
            ],
            width=12, # used to allow style width
            style={'background-color': 'grey', 'width': '98%'},
        )
    ],
    justify='center',
    class_name='g-0'
)

page_structure = [
    dbc.Row(
        [
            dbc.Col(
                html.P('This is column 1'),
                style={'background-color': 'cyan'},
                class_name='border',
                xs = 12 , sm = 12 , md  = 2, lg = 2, xl = 2,
            ),
            dbc.Col([
                #html.P('This is column 2'),
                content],
                style={'background-color': 'green', 'min-height':'100vh'},
                class_name='border',
                xs = 12 , sm = 12 , md  = 10, lg = 10, xl = 10,
            ),
        ],
        class_name='g-0'
    )
]

app.layout = dbc.Container(
    id='root',
    children=page_structure,
    fluid=True,
    class_name='g-0',
)

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

This is a result of this code:

White block represents container for the plot. It must stretch to the bottom line, or next object of the content column.

In my search I tried to write 'height': '100%' for each parent and 'height': '1px' in style of column 2 because of 'min-height': '100vh' property. But in that case graph container will create scroll and unfilled areas of main columns. See fig. below (changed color to orange for visibility):

Maybe there is a better approach for such cases?
Thank you!

I would suggest dropping some of the inner rows and columns in your solution. Rows and columns are only really useful when you have a row with multiple columns. Otherwise it’s just creating a lot of nesting.

Instead I think using CSS Flexbox is a good option here, because it allows you to create a column, and specify that one item should expand to fill available space. Read more about flexbox here, and about Bootstrap Flexbox utility classes here

Here’s a modified version of your example that does what you want. The second column is turned into a flex column with d-flex flex-column and we make the graph container expand to fill the available space with flex-grow-1.

import dash
import dash_bootstrap_components as dbc
from dash import html

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

graph_container = html.Div(
    style={"backgroundColor": "white"}, className="flex-grow-1"
)

content = html.Div(
    [
        html.P("This is column for content"),
        html.P("Sample text 1"),
        html.P("Sample text 2"),
        graph_container,
    ],
    className="h-100 d-flex flex-column",
)

page_structure = [
    dbc.Row(
        [
            dbc.Col(
                html.P("This is column 1"),
                style={"background-color": "cyan"},
                class_name="border",
                xs=12,
                md=2,
            ),
            dbc.Col(
                [content],
                style={"backgroundColor": "green", "height": "100vh"},
                class_name="border",
                xs=12,
                md=10,
            ),
        ],
        class_name="g-0",
    )
]

app.layout = dbc.Container(
    id="root",
    children=page_structure,
    fluid=True,
    class_name="g-0",
)

if __name__ == "__main__":
    app.run(debug=True)
1 Like

@tcbegley, thank you for the clarification about rows and columns usage! I will update my layouts.
Flexbox property works perfectly as well! I am very grateful to you!

1 Like

Hi @tcbegley ,

thank you for you hints. I am currently facing a comparable problem. I have a three column page between a header and a footer. I would like the content part in the middle to span vertically over all the space that is left, so that header and footer align with the top and bottom of the screen. So far I only got crude solutions that did not really fit the screen size. Do you have any hints?

from dash import Dash, html, dcc
import dash_bootstrap_components as dbc
import dash
import copy

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


"""
==========================================================================
footer/header
"""
# setup links for footer/header
footer_links = [
    
    {'name': 'Link 1', 'href': ''},
    {'name': 'Link 2', 'href': ''},
    {'name': 'Link 3', 'href': ''},
    {'name': 'Link 4', 'href': ''}
    
]

# setup columns footer/header
footer_cols = []

for i in range(0, len(footer_links)):
    
    link_col = dbc.Col([
            
            html.A(
                children = footer_links[i]['name'],
                href = footer_links[i]['href'],
                style = {'color': 'white', 'backgroundColor': 'black'},
                className = 'footer-link d-flex justify-content-center' # for horizonzal centering of column content
            )
           
    ],
    lg = 12 / len(footer_links), # column width on large screen
    xs = 12, # column width on small screen
    align = 'center' # for vertical centering in column
    )

    footer_cols.append(link_col)

# put together footer layout
footer_layout = dbc.Row(
                    footer_cols,
                    class_name = 'g-0',
                    style  = {'backgroundColor': 'black'},
                    justify = 'center' # for horizontal alignment of columns, only works if cols have a width
)

# create header by cloning footer
footer_header = copy.deepcopy(footer_layout)


"""
==========================================================================
mid column
"""

graph_container = html.Div(
    style={"backgroundColor": "red"}, className="flex-grow-1"
)

content = html.Div(
    [
        graph_container,
    ],
    className="h-100 d-flex flex-column",
)


"""
==========================================================================
layout
"""

app.layout = dbc.Container([
    
    # row - header
    footer_header,
    
    
    #row - page contents
    dbc.Row(
        [
            dbc.Col([
                html.P("Column 1"),
                dcc.Dropdown(),
                dcc.Dropdown(),
                dcc.Dropdown()
                
                ],
                style={"backgroundColor": "white"},
                lg = 2,
                xs = 12
            ),
            
            dbc.Col([
                content
                  ],
                lg = 8,
                xs = 12
            ),
            
            dbc.Col([
                html.P("Column 3"),
                dcc.Dropdown(),
                dcc.Dropdown(),
                dcc.Dropdown()
                
                ],
                style={"backgroundColor": "yellow"},
                lg = 2,
                xs = 12
            ),
            
        ],
        class_name="g-0"
    ),
    
    # row - footer
    footer_layout
    
    
    
],
fluid=True,
class_name="g-0",

)


if __name__ == "__main__":
    app.run(debug=True)

Nevermind, I figured it out myself. I had to turn all the rows and cols in which my page content sits into flex containers as well.

from dash import Dash, html, dcc
import dash_bootstrap_components as dbc
import dash
import copy

app = dash.Dash(__name__)




"""
==========================================================================
layout
"""

app.layout = dbc.Container([
    
    
    dbc.Row([
       
            dbc.Col([
                
                html.P('HEADER')
                
            ]) 
       
    ]),
    
    
    dbc.Row([
        
        dbc.Col([
            html.P('row1 - col1')
        ],
        md = 2,
        xs = 12,
        style = {'backgroundColor': 'red'}
        ),
            
        
        
        dbc.Col([
             html.P('row1 - col2')
        ],
        md = 8,
        xs = 12,
        style = {'backgroundColor': 'green'}
        ),
        
        
        
        dbc.Col([
              html.P('row1 - col3')
        ],
        md = 2,
        xs = 12,
        style = {'backgroundColor': 'blue'}
        )
        
           
    ],
    style = {'flexGrow': '1'}
    ),
    
    dbc.Row([
       
            dbc.Col([
                
                html.P('FOOTER')
                
            ]) 
       
    ]),
    
    
    
],
fluid=True,
style = {'height': '100vh', 'backgroundColor': 'yellow', 'display': 'flex', 'flexDirection': 'column'}  # die ganze app steckt in einem flex container; flex richtung ist column (standard); die row mit dem hauptinhalt bekommt flew grow

)


if __name__ == "__main__":
    app.run(debug=True)
2 Likes

Thanks for sharing the solution.