3

I am currently writing a Dash application, mostly using Dash Bootstrap Components. I am quite happy with the layout, but want to adjust the primary color to match my companies color scheme. In the picture below, I basically want to replace all the blue stuff with a different color.

Additional challenge is that due to the hosting environment, I am unfortunately limited to a single big Python file - I cannot have additional .css files.

I am using BOOTSTRAP_STYLESHEET = [dbc.themes.SPACELAB]. I know that I can replace single components' colors by using, e.g. style={'background-color':COMPANY_MAIN_COLOR}. Is there a way to instead replace SPACELAB's primary color with a different one? Or at least, to replace each component's default instead of having to do it manually for each component?

enter image description here

Thomas
  • 4,696
  • 5
  • 36
  • 71

1 Answers1

4

If you could add a css file I would go with that approach. Then you could simply overwrite the primary styles.

But since you indicated that isn't an option, you could create a wrapper function for your button that sets a default background color style:

MWE

from dash import Dash, html, dcc
import dash_bootstrap_components as dbc


def CustomButton(*args, **kwargs):
    default_color = "green"
    default_color_light = "lightgreen"
    default_color_dark = "darkgreen"
    kwargs.setdefault("style", {"background-color": default_color, "background-image": "-webkit-gradient(linear, left top, left bottom, from(lightgreen), to(darkgreen))"})
    return dbc.Button(*args, **kwargs)


app = Dash(external_stylesheets=[dbc.themes.SPACELAB])
app.layout = html.Div(
    [
        dbc.Button("Primary", color="primary", className="me-1"),
        CustomButton("Primary", color="primary", className="me-1")
    ]
)

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

result

This only sets default values so you can overwrite the color by setting the style property. If you don't want the gradient by default you can remove the background-image part from the setdefault call.

Update

Alternatively you could overwrite the styles with css by Customizing Dash's HTML Index Template.

The SPACELAB styles define a --primary css color variable, but it annoyingly doesn't use this variable anywhere. Different elements also might change the color in different ways so I don't think there's an easy catch-all way to do this. But you can use the following approach and add styles to it until it is as you want it to be

from dash import Dash, html, dcc
import dash_bootstrap_components as dbc

app = Dash(external_stylesheets=[dbc.themes.SPACELAB])
app.index_string = """
<!DOCTYPE html>
<html>
   <head>
       {%metas%}
       <title>{%title%}</title>
       {%favicon%}
       {%css%}
       <style>
           .btn-primary {
              background-image: linear-gradient(red, blue);
           }
           .custom-control-input:checked ~ .custom-control-label::before {
              border-color: red;
              background-color: red;
           }
       </style>
   </head>
   <body>
       {%app_entry%}
       <footer>
           {%config%}
           {%scripts%}
           {%renderer%}
       </footer>
   </body>
</html>
"""

app.layout = html.Div(
    [
        dbc.Button("Primary", color="primary", className="me-1"),
        dbc.Checklist(
            options=[
                {"label": "Option 1", "value": 1},
                {"label": "Option 2", "value": 2},
            ],
            value=[1],
            id="switches",
            switch=True,
        ),
    ],
)

if __name__ == "__main__":
    app.run_server()
5eb
  • 14,798
  • 5
  • 21
  • 65
  • The problem is that, as seen in the screenshot above, I need to change the color for not only the button, but also the toggle elements, the slider, and many more - basically all of the html elements. So I am wondering whether there is a way to declare that globally (e.g. in the top-level div element) and have it apply to all sub-elements... – Thomas Dec 27 '21 at 11:38
  • 1
    Not with these styles I think. The colors are hardcoded, we can't change the value of a css variable and have it apply for all elements that use the variable. We seem to need to override all these styles. I've updated my answer with approach that can do that. – 5eb Dec 27 '21 at 16:39
  • I've looked some more myself and this seems like the best approach with how things are currently. I will therefore mark this as the correct answer, thank you for your input. – Thomas Jan 03 '22 at 14:38