Scrollable navigation bar in multi-column layout

Hi there,
I’m trying to create a multi-column layout with a scrollable navigation bar in one of the columns (see screenshot and code below). The navigation bar recognizes the overflow and shows a scroll bar at the right but it is not scrollable. I would appretiate if someone could point out to me what I’m missing.

import dash
import dash_bootstrap_components as dbc
import dash
from dash import dcc
import dash_html_components as html

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

sidebar = dbc.Nav(
    [dbc.NavLink("test", href="/page-1") for i in range(30)],
    pills=True,
    vertical=True,
    style={"overflow": "scroll", "bottom": 0},
)


app.layout = maindiv = dbc.Container(
    [
        dbc.Row(
            [
                dbc.Col(
                    [
                        html.H2("Left Content", className="text-center"),
                        dbc.Row([sidebar], no_gutters=True,),
                    ],
                    style={"background-color": "yellow"},
                    width=3,
                    xs=5,
                    sm=4,
                    md=3,
                    lg=3,
                    xl=3,
                ),
                dbc.Col(
                    [html.H2("Middle Content", className="text-center"),],
                    style={"background-color": "orange"},
                    width=5,
                    xs=1,
                    sm=3,
                    md=5,
                    lg=5,
                    xl=5,
                ),
                dbc.Col(
                    [html.H1("Right Content", className="text-center"),],
                    style={"background-color": "yellow"},
                    width=4,
                    xs=6,
                    sm=5,
                    md=4,
                    lg=4,
                    xl=4,
                ),
            ],
            no_gutters=True,
        ),
    ],
    style={
        "background-color": "green",
        "padding": "0 1rem 0 1rem",
        "margin-left": "0",
        "margin-right": "0",
        "position": "fixed",
    },
    fluid=True,
)


if __name__ == "__main__":
    app.run_server(port=8888, use_reloader=True)

Hey @lechat

You can make a column scrollable by setting the column height at 100% and set the overflow to scroll. Then make the row the height of the viewport.

dbc.Row(
    [
        dbc.Col(
            [
                html.H2("Left Content", className="text-center"),
                dbc.Row([sidebar]),
            ],
            className="h-100 overflow-scroll",         
        ),
        dbc.Col(...),
        dbc.Col(...)
    ],
    className="vh-100",
)

@AnnMarieW Thanks for your quick reply. I have added the two className arguments as suggested (and removed the “position”:“fixed” argument in the style of the outermost row otherwise nothing happens). Then a new scrollbar at the right of the page appears and the entire page becomes scrollable. However, I only want a specific element (the dbc.Nav element in this case) in the first column to be scrollable while fixing the rest of the page. I have also tried adding the className = “h-100 overflow-scroll” argument directly in the row that contains the sidebar. So the question really is why does the scroll bar in the sidebar (which is clearly shown) not allow for scrolling?

@lechat,

Try this:

scroll

from dash import Dash, html
import dash_bootstrap_components as dbc


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

sidebar = dbc.Nav(
    [dbc.NavLink("test", href="/page-1") for i in range(30)],
    pills=True,
    vertical=True,
    # style={"overflow": "scroll", "bottom": 0},
)


app.layout = dbc.Container(
    [
        dbc.Row(
            [
                dbc.Col(
                    [
                        html.H2(
                            "Left Content",
                            className="text-center sticky-top",
                            style={"background-color": "yellow"},
                        ),
                        sidebar,
                    ],
                    className="h-100 overflow-scroll",
                    style={"background-color": "yellow"},
                    width=3,
                    xs=5,
                    sm=4,
                    md=3,
                    lg=3,
                    xl=3,
                ),
                dbc.Col(
                    [
                        html.H2("Middle Content", className="text-center"),
                    ],
                    style={"background-color": "orange"},
                    width=5,
                    xs=1,
                    sm=3,
                    md=5,
                    lg=5,
                    xl=5,
                ),
                dbc.Col(
                    [
                        html.H1("Right Content", className="text-center"),
                    ],
                    style={"background-color": "yellow"},
                    width=4,
                    xs=6,
                    sm=5,
                    md=4,
                    lg=4,
                    xl=4,
                ),
            ],
            className="vh-100"
            # no_gutters=True,
        ),
    ],
    style={
        "background-color": "green",
        "padding": "0 1rem 0 1rem",
        "margin-left": "0",
        "margin-right": "0",
        #   "position": "fixed",
    },
    fluid=True,
)


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


Thanks again. When I run your code I get the following:

So no scrollbar for the Nav element but again a bar for the entire page. Any idea what could be going on here?

In the mean time I have found a way that pretty much achieves what I want:

import dash
import dash_bootstrap_components as dbc
import dash_html_components as html

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

sidebar = dbc.Container( 
    dbc.Nav(
        [dbc.NavLink("test", href="/page-1") for i in range(30)],
        pills=True,
        vertical=True,
    ),
    style={"overflowY": "scroll", "height": "90vh", "background-color": "cyan"},
)


app.layout = dbc.Container(
    [
        dbc.Row(
            [
                dbc.Col(
                    [
                        html.H2("Left Content", className="text-center"),
                        dbc.Row([sidebar], no_gutters=True,),
                    ],
                    style={"background-color": "yellow",},
                    width=3,
                    xs=5,
                    sm=4,
                    md=3,
                    lg=3,
                    xl=3,
                ),
                dbc.Col(
                    [html.H2("Middle Content", className="text-center"),],
                    style={"background-color": "orange"},
                    className="vh-100",
                    width=5,
                    xs=1,
                    sm=3,
                    md=5,
                    lg=5,
                    xl=5,
                ),
                dbc.Col(
                    [html.H1("Right Content", className="text-center"),],
                    style={"background-color": "yellow"},
                    className="vh-100",
                    width=4,
                    xs=6,
                    sm=5,
                    md=4,
                    lg=4,
                    xl=4,
                ),
            ],
            no_gutters=True,
            className="vh-100",
        ),
    ],
    style={
        "background-color": "green",
        "padding": "0 1rem 0 1rem",
        "margin-left": "0",
        "margin-right": "0",
        "position": "fixed",
    },
    fluid=True,
)


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

which produces:

So basically I had to wrap the Nav element into a Container. The only imperfection is that if I fix the height of the container containing the Nav element to 100vh it gets cut off a bit at the bottom depending on the window size (so I put it to 90vh for my screen size). Any idea how I can make it always match up with the lower edge of the page upon resizing the window or using a different screen size?

That’s odd - did you copy and paste my example and run it without any changes? What version of dash and dbc are you using?

Yes I copy pasted it. I have dash v 2.1.0 and dbc v 1.0.2. I updated dash to the latest version 2.2.0 but the behaviour is the same.

Oh, I see what’s wrong. You actually aren’t using dbc 1.0.2.

You can include this to see what version is running in the app:

print(dbc.__version__)

Also, if you are on the current version of dbc, then no_gutters=True doesn’t work. You need to set the gutters with the utility classes: className="g-0"

Here is a cheatsheet you might find helpful: https://dashcheatsheet.pythonanywhere.com/

You can find more info in this post: Dash Bootstrap Components Cheatsheet

You’re right. If I print the dbc version from the running app it gives v 0.8.3. Why is it not using the same version as the anaconda environment I’m running it from and how can I change that?

I haven’t used anaconda, so I’m not sure.

If anyone else knows the answer, please feel free to jump in here :slight_smile: