Dash Mantine Components Dynamic Element Sizing

I’m trying make a Dash web app using Mantine components. The design goal is to have three columns, where each column extends to the bottom of the screen but no further. Inside each column will be a scroll area that allows the content to be visible if the available screen area isn’t sufficient. I also want the column area to be the same extent regardless of how much content is present in the column.

Below is a minimal app to illustrate my problems. The problems are that the left (empty) column appears very short and the other two columns expand to the size of the content. If the app is working as intended, all three columns should have identical height, extending close to the bottom of the screen. I’ve tried to get Gemini, GPT-5 and Sonnet 3.7 to fix these problems and they couldn’t figure it out. Thanks for any help you can offer!

from dash import Dash
import dash_mantine_components as dmc


app = Dash()

left_col = dmc.Stack([
    dmc.Space(),
    dmc.Center(dmc.Button(
        "Dummy Button",
        variant="filled",
        color="gray",
    )),
    dmc.Space(),
    dmc.Paper(
        dmc.ScrollArea(
            # 100*"This is left column content.  ",
            h="100%",
        ),
        radius="sm",
        p="xl",
        shadow="sm",
        withBorder=True,
    )
])

center_col = dmc.Stack([
    dmc.Space(),
    dmc.Center(dmc.Button(
        "Dummy Button",
        variant="filled",
        color="gray",
    )),
    dmc.Space(),
    dmc.Paper(
        dmc.ScrollArea(
            100*"This is middle column content.  ",
            h="100%",
        ),
        radius="sm",
        p="xl",
        shadow="sm",
        withBorder=True,
    )
])

right_col = dmc.Stack([
    dmc.Space(),
    dmc.Center(dmc.Button(
        "Dummy Button",
        variant="filled",
        color="gray",
    )),
    dmc.Space(),
    dmc.Paper(
        dmc.ScrollArea(
            100*"This is right column content.  ",
            h="100%",
        ),
        radius="sm",
        p="xl",
        shadow="sm",
        withBorder=True,
    )
])

layout = dmc.AppShell(
    [
        dmc.AppShellHeader(
            dmc.Group(
                [
                    dmc.Group(
                        [
                            dmc.Title("Column Height Demo", c="gray"),
                        ]
                    ),
                ],
                justify="space-between",
                h="100%",
                px="md",
            ),
        ),
        dmc.AppShellMain(
            dmc.Grid(
                [
                    dmc.GridCol(left_col, span=4),
                    dmc.GridCol(center_col, span=4),
                    dmc.GridCol(right_col, span=4),
                ],
                gutter="xl",
            ),
        ),
    ],
    header={"height": 60},
    navbar={
        "width": 300,
        "breakpoint": "sm",
        "collapsed": {"desktop": True, "mobile": True},
    },
    padding="md",
    id="appshell",
)

app.layout = dmc.MantineProvider(layout)


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

Hi, you should try to change h=100% in ScrollArea to a value like 100 but add h = “100%” to the dmc.Stack. Something as below:

left_col = dmc.Stack([
    dmc.Space(),
    dmc.Center(dmc.Button(
        "Dummy Button",
        variant="filled",
        color="gray",
    )),
    dmc.Space(),
    dmc.Paper(
        dmc.ScrollArea(
            # 100*"This is left column content.  ",
            h=100,
        ),
        radius="sm",
        p="xl",
        shadow="sm",
        withBorder=True,
    )
], h="100%")

1 Like

Thanks for your help @hoatran! Your suggestion isn’t quite what I was looking for because it locks the scroll area to 100 pixels in height, regardless of the screen’s resolution. However, your suggestion got me close enough that I was able to find a solution. Not sure if there’s a better solution or not, but this seems to work!

from dash import Dash
import dash_mantine_components as dmc


app = Dash()

header_plus_control_row_height = "260px" # approx height of the header row + controls row

left_col = dmc.Stack([
    dmc.Space(),
    dmc.Center(dmc.Button(
        "Dummy Button",
        variant="filled",
        color="gray",
    )),
    dmc.Space(),
    dmc.Paper(
        dmc.ScrollArea(
            # 100*"This is left column content.  ",
            style={"height": f"calc(100vh - {header_plus_control_row_height})"},
        ),
        radius="sm",
        p="xl",
        shadow="sm",
        withBorder=True,
        style={"flex": 1}
    )
], style={"height": "100%", "display": "flex", "flexDirection": "column"})

center_col = dmc.Stack([
    dmc.Space(),
    dmc.Center(dmc.Button(
        "Dummy Button",
        variant="filled",
        color="gray",
    )),
    dmc.Space(),
    dmc.Paper(
        dmc.ScrollArea(
            100*"This is middle column content.  ",
            style={"height": f"calc(100vh - {header_plus_control_row_height})"},
        ),
        radius="sm",
        p="xl",
        shadow="sm",
        withBorder=True,
        style={"flex": 1}
    )
], style={"height": "100%", "display": "flex", "flexDirection": "column"})

right_col = dmc.Stack([
    dmc.Space(),
    dmc.Center(dmc.Button(
        "Dummy Button",
        variant="filled",
        color="gray",
    )),
    dmc.Space(),
    dmc.Paper(
        dmc.ScrollArea(
            100*"This is right column content.  ",
            style={"height": f"calc(100vh - {header_plus_control_row_height})"},
        ),
        radius="sm",
        p="xl",
        shadow="sm",
        withBorder=True,
        style={"flex": 1}
    )
], style={"height": "100%", "display": "flex", "flexDirection": "column"})

layout = dmc.AppShell(
    [
        dmc.AppShellHeader(
            dmc.Group(
                [
                    dmc.Group(
                        [
                            dmc.Title("Column Height Demo", c="gray"),
                        ]
                    ),
                ],
                justify="space-between",
                h="100%",
                px="md",
            ),
        ),
        dmc.AppShellMain(
            dmc.Grid(
                [
                    dmc.GridCol(left_col, span=4),
                    dmc.GridCol(center_col, span=4),
                    dmc.GridCol(right_col, span=4),
                ],
                gutter="xl",
            ),
        ),
    ],
    header={"height": 60},
    navbar={
        "width": 300,
        "breakpoint": "sm",
        "collapsed": {"desktop": True, "mobile": True},
    },
    padding="md",
    id="appshell",
)

app.layout = dmc.MantineProvider(layout)


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

1 Like