dbc.Table increases height of div and creates a lot of whitespace

Hi,

in my app I have an html.Div in which I want to put a dbc.Table. This table can get very long. In case it gets longer than the Div a vertical scroll bar is supposed to appear. With my current setup the table somehow influences the size of its parent Div. A scroll bar for the Div appears, but somehow I also get a scrollbar for the page because a lot of whitespace appears below the Div.:

I tried to put a dcc.Graph into the Div instead of the table. In this case everything works fine, the Div keeps its size and I can scroll through it to view the whole graph:

It appears to me that dbc.Table has a different behaviour than other elements.

I created a small example app for you to see the difference. The graph/table is supposed to fit in the green box. By clicking the button on the left one can switch between graph and table:

import dash
from dash import Dash, html, dcc, Input, Output, State, callback, dash_table, ClientsideFunction, ALL, clientside_callback, ctx
import dash_bootstrap_components as dbc
import pandas as pd
import plotly.express as px



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


# main container
app.layout = dbc.Container([
                
    
                    dbc.Row([
                        
                        # column 1 - button for changing between table and graph
                        dbc.Col([
     
                            html.Button(id = 'button', children = 'show table or graph', n_clicks = 0), 
           
                        ],
                        md = 2,
                        xs = 12,
                        ),
                        
                        
                        # column 2 - graph/table
                        dbc.Col([
                            
                             html.Div(
                                 id = 'content-container',
                                 children= 'table and graph are not supposed to overflow this area',
                                 style = {'height': '40%', 'backgroundColor': 'lightgreen', 'overflow': 'auto'}
                             )
                       
                        ],
                        md = 10,
                        xs = 12,  
                        ),
                          
                    ],
                    className = 'pb-2',
                    style = {'flexGrow': '1'}
                    ),            
                          

],
fluid = True,
style = {'height': '100vh', 'display': 'flex', 'flexDirection': 'column', 'flexGrow': '1'}
)   



@callback(Output('content-container', 'children'),
          Input('button', 'n_clicks') , prevent_initial_call=True,  
)
def create_table_or_graph(n_clicks):
        
    
        # create df
        df = pd.DataFrame({
            "numbers": [i for i in range(1, 50)],
            "more_numbers": [i for i in range(1, 50)],
            "even_more_numbers": [i for i in range(1, 50)]
        })
    

        # odd number -> table
        if not (n_clicks % 2) == 0 :

            table = dbc.Table.from_dataframe(df)
            
            return table
    
        # else -> graph
        else:
            
            fig = px.scatter(df, x="numbers", y="more_numbers")
            
            graph  =  dcc.Graph(
                        id='example-graph',
                        figure=fig
            )

            return graph
        

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

Any hints on how to mitigate the issue are highly appreciated. In case anyone is wondering why I am using dbc.Table: it allows copying data from the table cells and there are no accessibility issues with it.

I think you could return a Div including table and then style for that Div. Something as below:

@callback(Output('content-container', 'children'),
          Input('button', 'n_clicks') , prevent_initial_call=True,  
)
def create_table_or_graph(n_clicks):
        # create df
        df = pd.DataFrame({
            "numbers": [i for i in range(1, 50)],
            "more_numbers": [i for i in range(1, 50)],
            "even_more_numbers": [i for i in range(1, 50)]
        })
    
        # odd number -> table
        if not (n_clicks % 2) == 0 :
            table = dbc.Table.from_dataframe(df)
            return html.Div(table,style={'overflow-y':'auto','height': 280, 'backgroundColor': 'lightgreen'})

And I think you can delete style = {'height': '40%', 'backgroundColor': 'lightgreen', 'overflow': 'auto'} too.

Thank you @hoatran . This works, but is not exactly what I want to achieve. I want the table to fit into a div which has a relative height of 40% of the screen. Setting the height to a fixed 280 pixels introcudes a static quality I would like to avoid.

1 Like

So maybe change from fixed 280 pixel to 100vh should help. Something as below:

@callback(Output('content-container', 'children'),
          Input('button', 'n_clicks') , prevent_initial_call=True,  
)
def create_table_or_graph(n_clicks):
        # create df
        df = pd.DataFrame({
            "numbers": [i for i in range(1, 50)],
            "more_numbers": [i for i in range(1, 50)],
            "even_more_numbers": [i for i in range(1, 50)]
        })
    
        # odd number -> table
        if not (n_clicks % 2) == 0 :
            table = dbc.Table.from_dataframe(df)
            return html.Div(table,style={'height':'100vh', 'backgroundColor': 'lightgreen'})
1 Like

Thanky @hoatran, using height with vh solved my problem. Although using 100vh was a little too much (I got a scroll bar for the page again). I reduced it to 90vh.