Dash Bootstrap Templates

Dash Bootstrap Templates

See these features live at : Dash

dash-bootstrap-templates library provides:

  • Bootstrap themed Plotly figure templates. You will find a Plotly template for each of the 26 Bootstrap/Bootswatch themes available in the
    Dash Bootstrap Components Library. These templates will automatically style your figures with Bootstrap theme colors and fonts.

  • Two All-in-One components to change themes in a Dash app.

    • ThemeSwitchAIO toggles between two themes.
    • ThemeChangerAIO select from multiple themes.
  • The dbc.css stylesheet which styles Dash Core Components and the Dash DataTable with a Bootstrap theme.

Note: The ThemeSwitchAIO and ThemeChangerAIO components and the dbc.css stylesheet requires Dash Bootstrap Components>=V1.0.0. It will only
work with the themes included in Dash Bootstrap Components>=V1.0.0.

Figure Template Quickstart

pip install dash-bootstrap-templates

Learn more about Plotly figure templates and themes at: Theming and templates in Python

"""
A sample of 8 of the 26 Bootstrap themed Plotly figure templates available
in the dash-bootstrap-template library

"""
from dash import Dash, html, dcc
import dash_bootstrap_components as dbc
from dash_bootstrap_templates import load_figure_template
import plotly.express as px

df = px.data.gapminder()

templates = [
    "bootstrap",
    "minty",
    "pulse",
    "flatly",
    "quartz",
    "cyborg",
    "darkly",
    "vapor",
]

load_figure_template(templates)

figures = [
    px.scatter(
        df.query("year==2007"),
        x="gdpPercap",
        y="lifeExp",
        size="pop",
        color="continent",
        log_x=True,
        size_max=60,
        template=template,
        title="Gapminder 2007: '%s' theme" % template,
    )
    for template in templates
]

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

app.layout = dbc.Container([dcc.Graph(figure=fig, className="m-4") for fig in figures])

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

image
image
image
image

figure_template2

dbc.css stylesheet

The dash-core-components, the Dash DataTable and Plotly figures are not automatically styled with a Bootstrap theme.
An easy way to make your Dash components look better with a Bootstrap theme is to use the stylesheet from
the dash-bootstrap-templates library. This stylesheet defines the “dbc” class.

Adding className="dbc" minimally styles Dash components with your selected Bootstrap theme:

  • Makes the text readable in both light and dark themes.
  • Uses theme’s font-family.
  • Changes the accent color to the theme’s primary color

You can add the dbc class as an external stylesheet like this:

dbc_css = ("https://cdn.jsdelivr.net/gh/AnnMarieW/dash-bootstrap-templates@V1.0.2/dbc.min.css")
app = dash.Dash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP, dbc_css])

Add className="dbc" to the outer container of the app or a component like this:

app.layout = dbc.Container(
    [
        ...
    ],
    fluid=True,
    className="dbc"
)

That’s it! Simply adding className="dbc" will make Dash Core Components and the DataTable look better with ALL themes included in the dash-bootstrap-components library.

See a live demo at: Dash

If you have suggestion for improvements or if you find a bug, please let us know on the issue tracker

Requires dash-bootstrap-components>=V1.0.0

Theme Switcher Components

See a live demo at Dash

dash-bootstrap-templates has two All-in-One components to change themes.

  • The ThemeSwitchAIO is a switch with icons on the left and right, which is ideal for toggling between a light and a dark theme.
  • The ThemeChangerAIO has a button that opens an dbc.Offcanvas component which by default shows all the available themes.

Note the All-in-One component switches the Bootstrap stylesheet for the app and sets the default Plotly figure template for the theme, however, figures must be updated in a callback in order to render the figure with the new template.

See the callback below for an example. The template_from_url is a helper function that returns the template name based on the theme url. For example template_from_ur(dbc.themes.SLATE) returns "slate"

ThemeChangerAIO Quickstart


from dash import Dash, dcc, html, Input, Output
import pandas as pd
import plotly.express as px
import dash_bootstrap_components as dbc
from dash_bootstrap_templates import ThemeChangerAIO, template_from_url


dbc_css = (
    "https://cdn.jsdelivr.net/gh/AnnMarieW/dash-bootstrap-templates@V1.0.1/dbc.min.css"
)
app = Dash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP, dbc_css])


df = pd.DataFrame(
    {
        "Fruit": ["Apples", "Oranges", "Bananas", "Apples", "Oranges", "Bananas"],
        "Amount": [4, 1, 2, 2, 4, 5],
        "City": ["SF", "SF", "SF", "Montreal", "Montreal", "Montreal"],
    }
)
header = html.H4(
    "ThemeChangerAIO Demo", className="bg-primary text-white p-4 mb-2 text-center"
)
buttons = html.Div(
    [
        dbc.Button("Primary", color="primary"),
        dbc.Button("Secondary", color="secondary"),
        dbc.Button("Success", color="success"),
        dbc.Button("Warning", color="warning"),
        dbc.Button("Danger", color="danger"),
        dbc.Button("Info", color="info"),
        dbc.Button("Light", color="light"),
        dbc.Button("Dark", color="dark"),
        dbc.Button("Link", color="link"),
    ],
    className="m-4",
)
graph = html.Div(dcc.Graph(id="graph"), className="m-4")

app.layout = dbc.Container(
    [
        header,
        dbc.Row(
            [
                dbc.Col(ThemeChangerAIO(aio_id="theme", radio_props={"value":dbc.themes.FLATLY}), width=2,),
                dbc.Col([buttons, graph],width=10),
            ]
        ),
    ],
    className="m-4 dbc",
    fluid=True,
)


@app.callback(
    Output("graph", "figure"), Input(ThemeChangerAIO.ids.radio("theme"), "value"),
)
def update_graph_theme(theme):
    return px.bar(
        df, x="Fruit", y="Amount", color="City", barmode="group", template=template_from_url(theme)
    )


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

theme_changer



Here is the same app, but using a the ThemeSwitchAIO component to toggle between two themes.
See the (code here).

It’s also possible to change the icons. See an example of using Bootstrap icons instead of the default FontAwesome
icons here.

theme_toggle

Background

Dash Labs is Plotly library that explores new features for future releases of Dash.
In Dash Labs V0.4.0, there was a cool feature where Bootstrap themed figure templates were created “on the fly”. This was a
part of the layout templates project that is no longer being developed.

Even though these Bootstrap themed figure templates will not be included in Dash, the dash-bootstrap-templates makes
them available to you. The figure templates are created using the Dash Labs’ algorithms and saved in json format. When
you use load_figure_template() in your app, it loads the json file, adds it to plotly.io and sets it as the default figure template for an app. See more
information about Plotly figure templates here.

Available Themes

This library provides a figure template for the following Bootstrap/Bootswatch themes:

valid_themes = [
“bootstrap”,
“cerulean”,
“cosmo”,
“flatly”,
“journal”,
“litera”,
“lumen”,
“lux”,
“materia”,
“minty”,
“pulse”,
“sandstone”,
“simplex”,
“sketchy”,
“spacelab”,
“united”,
“yeti”,
“cyborg”,
“darkly”,
“slate”,
“solar”,
“superhero”,
“morph”,
“quartz”,
“vapor”
“zephyr”
]

9 Likes

This is awesome work. Thank you, and I’m enjoying iterating multiple charts quicker this way.

Not an issue, but a thought that it would be great to get this up on conda-forge for installing with conda sometime (I someday will learn how to help do things like that). For now I’ve installed it with pip, but as I understand when working in an anaconda virtual environment it’s best to manage the packages with conda as much as possible to keep things straight. Newer to dash so I’m not sure if the community is using conda as much.

Hi @kmhurchla

Glad you like the dash-bootstrap-templates library! I just updated the original post for the new features in V1.0.4 such as the theme change components and the stylesheet to apply your selected Bootstrap theme to Dash Core Components and the DataTable. You can see a live demo here:
https://hellodash.pythonanywhere.com/

Thanks for the suggestion of adding it to conda. I’ve never done that before, so if anyone can give me some guidance, I’d appreciate it! :slightly_smiling_face:

1 Like

Awesome thanks AnnMarie! I’m definitely playing catchup with posts and versions 8)

Really great work. Thank you. Is there a way to define the template global so that I don’t need to set it in every px figure in Plotly?

Hi @Gobrel - glad you like the bootstrap-themed figure templates :slightly_smiling_face:

Great question! When you load the template, it automatically makes it the default template for the app.

from dash_bootstrap_templates import load_figure_template
load_figure_template("cyborg")

If you load multiple templates , then it makes both templates available for use in the app and sets the first template (in this example: “minty”) as the default:

from dash_bootstrap_templates import load_figure_template
load_figure_template(["minty", "cyborg"])

See more information on how to set or change the default Plotly figure template here.

In this example, note that you don’t have to specify the template when you create the figures:


from dash import Dash, dcc, html
import plotly.express as px
import dash_bootstrap_components as dbc

from dash_bootstrap_templates import load_figure_template

# This loads the "cyborg" themed figure template from dash-bootstrap-templates library,
# adds it to plotly.io and makes it the default figure template.
load_figure_template("cyborg")

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

df = px.data.gapminder()

dff = df[df.year.between(1952, 1982)]
dff = dff[dff.continent.isin(df.continent.unique()[1:])]
line_fig = px.line(
    dff, x="year", y="gdpPercap", color="continent", line_group="country"
)

dff = dff[dff.year == 1982]
scatter_fig = px.scatter(
    dff, x="lifeExp", y="gdpPercap", size="pop", color="pop", size_max=60
).update_traces(marker_opacity=0.8)

avg_lifeExp = (dff["lifeExp"] * dff["pop"]).sum() / dff["pop"].sum()
map_fig = px.choropleth(
    dff,
    locations="iso_alpha",
    color="lifeExp",
    title="%.0f World Average Life Expectancy was %.1f years" % (1982, avg_lifeExp),
)

hist_fig = px.histogram(dff, x="lifeExp", nbins=10, title="Life Expectancy")

graphs = html.Div(
    [
        dbc.Row(
            [
                dbc.Col(dcc.Graph(figure=line_fig), lg=6),
                dbc.Col(dcc.Graph(figure=scatter_fig), lg=6),
            ],
            className="mt-4",
        ),
        dbc.Row(
            [
                dbc.Col(dcc.Graph(figure=hist_fig), lg=6),
                dbc.Col(dcc.Graph(figure=map_fig), lg=6),
            ],
            className="mt-4",
        ),
    ]
)

heading = html.H1("Dash Bootstrap Template Demo", className="bg-primary text-white p-2")

app.layout = dbc.Container([heading, graphs], fluid=True)


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

1 Like

@AnnMarieW thanks you vermy much. Do you by any chances know what font the defauls dash bootstrap theme “Bootstrap” is using?

Hi @Gobrel

Here’s one way: You can get the URL for the stylesheet like this:

print(dbc.themes.BOOTSTRAP)

https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css

Now to get a human readable version take out the .min

https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.css

When you go to this site you will see all the classes for that theme.

Here’s another way – if you inspect the page of an app using the dbc.themes.BOOTSTRAP, can see all the fonts:

3 Likes

Hey Ann!

I’m late to the party but this is simply amazing! I’m using this in my project right now.

I have a radio item where the user can select the theme but I am having trouble persisting the theme across page refreshes though. It always resets to the default theme. Any tips on how to persist the theme?

Hi @winstonchiong

Glad you like the library!

See the Persistence section near the bottom of this page

Let me know if that works for you or if you would like a complete minimal example.