The answer is a modified html table
from dash import html, dcc
import dash_bootstrap_components as dbc
def table_cell(content, col_span, row_span=1):
if type(content) == str:
content = dbc.Alert(content, style={'height': '100%', 'margin': '0px', 'border-width': '5px', 'border-color': 'black'}),
return html.Td(
content,
colSpan=col_span,
rowSpan=row_span,
style={'margin': '0px', 'padding': '0px'},
)
def generate_layout():
return html.Div([
html.Table([
html.Colgroup([
html.Col(style={'width': '8.33%'}),
html.Col(style={'width': '8.33%'}),
html.Col(style={'width': '8.33%'}),
html.Col(style={'width': '8.33%'}),
html.Col(style={'width': '8.33%'}),
html.Col(style={'width': '8.33%'}),
html.Col(style={'width': '8.33%'}),
html.Col(style={'width': '8.33%'}),
html.Col(style={'width': '8.33%'}),
html.Col(style={'width': '8.33%'}),
html.Col(style={'width': '8.33%'}),
html.Col(style={'width': '8.33%'}),
]),
html.Tr([table_cell('data_trace', 6),
table_cell('data_trace_zoom', 3),
table_cell('info_box', 3, 2)]),
html.Tr([table_cell('event_trace', 6), table_cell('event_trace_zoom', 3)]),
html.Tr([table_cell('counts_per_s', 6),
table_cell('counts_hist', 3),
table_cell('heatmap', 3, 2)]),
html.Tr([table_cell('flow_rate_per_s', 6),
table_cell('flow_rate_hist', 3)]),
html.Tr([table_cell('conc_per_s', 6), table_cell('peak_profiles', 6)]),
], style={'display': 'table', 'width': '100%', 'border-collapse': 'collapse', 'height': '100%'})
], style={'height': '100vh'})