Show and Tell - Dash Bootstrap Components

Sticking with the documentation example, i changed the css theme to Simplex, and noticed an issue with the components spacing/alignment after the change. Why is that?

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

_navbar = dbc.Navbar(
    brand="Demo",
    brand_href="#",
    sticky="top",
    color="primary",
    dark="True",
    children=[
        dbc.DropdownMenu(
            nav=True,
            in_navbar=True,
            label="Menu",
            children=[
                dbc.DropdownMenuItem("Entry 1"),
                dbc.DropdownMenuItem("Entry 2"),
                dbc.DropdownMenuItem(divider=True),
                dbc.DropdownMenuItem("Entry 3"),
            ],
        ),
        dbc.NavItem(dbc.NavLink("Link", href="#")),
    ],
)

_body = dbc.Container(
    [
        dbc.Row(
            [
                dbc.Col(
                    [
                        html.H2("Heading"),
                        html.P(
                            "Donec id elit non mi porta gravida at eget metus. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. Etiam porta sem malesuada magna mollis euismod. Donec sed odio dui. Donec id elit non mi porta gravida at eget metus. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. Etiam porta sem malesuada magna mollis euismod. Donec sed odio dui."
                        ),
                        dbc.Button("View details", color="secondary"),
                    ],
                    md=4,
                ),
                dbc.Col(
                    [
                        html.H2("Graph"),
                        dcc.Graph(
                            id="dash-docs-graph",
                            figure={"data": [{"x": [1, 2, 3], "y": [1, 4, 9]}]},
                        ),
                    ]
                ),
            ]
        )
    ],
    className="docs-content",
)
external_stylesheets = [dbc.themes.SIMPLEX]

app = Dash(
    __name__,
    external_stylesheets=external_stylesheets
)

app.layout = html.Div([_navbar, _body])

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

Good catch @ndbcorp, the top margin is being applied by the docs-content class on the Container in _body, which is defined in our docs stylesheet, and so if you just copy paste the code on the docs homepage (which you definitely ought to be able to do without issue!) you won’t have that defined anywhere. You’ll actually see the same issue with regular bootstrap styling.

I’ve raised an issue on our repo, and will update the docs. In the mean time just change className="docs-content" to className=mt-4 (the classes mt-* are bootstrap classes for applying top margins easily) and things should look better, or if you prefer add a top margin with the style argument of Container. Note though that using the mt-* classes will mean that if you switch to a different theme it should adjust the margin appropriately for that theme, so it’s probably preferable.

EDIT - I’ve updated the example in the docs to use Bootstrap classes. Hopefully if you run that now you should see a margin at the top of the demo app.

Ok got it fixed on my end, thanks.

I am no css expert, so excuse the following question if its an obvious answer . Is it possible to have 2 style sheets to use in my app. Lets say i want to use the SIMPLEX theme from dbc to style certain components like the navbar, but i also want to use https://codepen.io/chriddyp/pen/bWLwgP120 to style other components in my app. Can i use both? Do i need to create my own style sheet combining the desired styling from each? What do you recommend?

You can definitely use multiple Stylesheets together. Just be aware that if they haven’t been designed to be used together they may clash on some things and give weird behaviour.

Hi @tcbegley

Any updates on the examples that will be added to the documentation as mentioned above?

Hey @sriotti

Thanks for your interest and patience! I don’t have the sidebar example for you yet, but that’s next on my list of things to do.

We’ve most recently been working on a more customisable Navbar component as discussed above (check this pull request if you’re interested), that will be released pretty soon.

I’ve also started work on cleaning out the examples directory of our repo. There’s a few ports of RShiny examples in there at the moment as well as demos of the components. We’ll continue adding examples there, including the multi-page examples.

In the meantime, you could check out @nedned’s slapdash repo, which has a sidebar layout that uses dash-bootstrap-components.

3 Likes

Really loving dash-bootstraps-components and the ease of implementing themes from Bootstwatch.

What is the best approach to styling tables? I’m using the dcc.DataTable component, but it doesn’t have a className attribute.

2 Likes

Hey @Chris369,

I don’t know if there’s a great way to style the DataTable using Bootstrap CSS. The component uses mostly inline styles which can be a little bit tricky to override with CSS classes.

If you’re willing to compile your own Bootstrap stylesheet using sass, here’s an approach that worked for me. The basic idea is that since we can’t apply the .table class to the DataTable, we instead wrap the DataTable in an element with a particular id like table-wrapper, then add selectors like the following to your stylesheet:

#table-wrapper table {
  /* styles from .table class */
}

You could write this stylesheet manually, but that would be really tedious. Sass lets you inherit / extend existing selectors. Here’s a bit more detail:

  1. Download Bootstrap source from Bootstrap website.

  2. In the source folder there’s a directory called scss, that’s the one we want, copy that to your working directory.

  3. Wrap your table in a div with a particular id like this:

app.layout = html.Div(dash_table.DataTable(...), id="table-wrapper")
  1. Create your scss file, I called mine table-shim.scss, and write something like this:
@import "scss/bootstrap.scss";

#table-wrapper table{
  @extend .table;
  @extend .table-striped;
  @extend .table-hover;
  @extend .table-bordered;
  font-family: inherit;
  --border: none;
}

This basically says we want to create a new selector that will select any table that is a child of an element with id table-wrapper, and apply all the styles of the classes .table, .table-striped etc. to it. I also added the font-family and --border arguments as they weren’t specified by Bootstrap so it defaulted to the DataTable defaults.

  1. Compile with sass sass table-shim.scss assets/my-bootstrap.css or similar. See here for how to install sass.

That’s it, run your app and hopefully it should work! As a final note, this worked for me with Bootswatch styles too. Just grab the _variables.scss and _bootswatch.scss files for the theme you’re interested in from the Bootswatch website (I tried it with the “Lux” theme), and change the imports in your scss file to something like

@import "lux/_variables.scss";
@import "scss/bootstrap.scss";
@import "lux/_bootswatch.scss";

Depending on the theme you choose, you might have to make additional adjustments if the styles clash with the styles set by DataTable. I don’t know for example how the dark Bootswatch themes would work with this approach.

Let me know how you get on if you try it, and definitely let me know how you get on if you find an easier way!

2 Likes

Thank you very much for your detailed instructions :slightly_smiling_face: I’m only just getting started with Bootstrap/CSS and so this sounds rather complicated at the moment! But is definitely something I’ll work towards! Thanks again.

1 Like

So I’ve been giving this ago, using Koala to compile my custom scss file [table-custom.scss]:

@import "../flatly/_variables.scss.css";
@import "bootstrap.scss";
@import "../flatly/_bootswatch.scss.css";

#table-wrapper table{
  @extend .table;
  @extend .table-striped;
  @extend .table-hover;
  @extend .table-bordered;
  font-family: inherit;
  --border: none;
}

Using this code in my dash app:

app = dash.Dash(__name__, external_stylesheets=['/scss/table-custom.css'])

But when I run my app I seem to have lost all the flatly styling?

This is my folder structure:

Where’ve I gone wrong?

The process for linking local CSS is a bit different to linking to external CSS via a CDN. Check out the Dash docs for detailed instructions, but the easiest way is to create a folder called assets in the same folder as your main app script, and just place the CSS (i.e. the compiled table-custom.css) in there. Dash will automatically detect and link it for you.

The local CSS you compiled replaces the need for any external CSS, so just ignore the external_stylesheets argument now. Sorry for the confusion!

EDIT - Also, I just noticed that your imports @import "../flatly/_variables.scss.css"; look like they have an unneeded .css in there, change it to @import "../flatly/_variables.scss"; (make sure the file name matches obviously). Same for _bootswatch.scss.

1 Like

Thank you so much! I have got it to work :slightly_smiling_face: At first I was getting sort of a flaty theme with slightly different colours, but I’ve removed those additional .css’s as advised and it looks as expected now. (I’m not sure why the extra .css’s were there - when I downloaded the scss files my computer seemed to add .css automatically!).

Now if I have more than one table I can’t use the same id=‘table-wrapper’. So am I write in thinking I just create a ‘table-wrapper2’ in my scss, recompile, and use the new id for table 2?

Great! Glad it’s working :slight_smile:

The table doesn’t need to be an immediate child of table-wrapper, it just needs to be contained inside one, so if you like you could just give your top-level component the id table-wrapper, like app.layout = html.Div(..., id="table-wrapper"), and the styles will be applied to every table in your app. That also means your CSS / Sass doesn’t have to change when you change the layout of your app and should be a lot more maintainable.

Amazing - thank you! :grinning:

1 Like

@tcbegley I just wanted to say thanks, I finally got around to really trying to implement this on my apps last week and after a day of getting to understand Bootstrap a little bit it’s made the job of laying out my sites much simpler and more flexible.

One thing I was trying and failing to do, which I now suspect was just the wrong approach, was getting animations to work with real layout changes.

E.g. with 2 columns I wanted 1 to disappear, I tried using collapse and setting the width to zero but it made the the 2nd column fall below the 1st column and then the collapse occurred causing the 2nd column to then jump up. I assume this was just not how this was conceived to be used?

1 Like

Glad you’ve enjoyed using it :slight_smile:

Could you describe a bit more the effect you’re going for? Also any kind of code snippet that shows what you tried in a little bit more detail. You’re right that the collapse is not really designed for this, but there might be a way to achieve the effect you want with a little bit of hacking.

Col doesn’t do any input validation (perhaps it should), so if you set width=0 the Col will try to apply a class called col-0 which doesn’t exist, and it will call back on the default behaviour specified in the col class which is probably why you saw the column expand and wrap onto a new line.

So this has been really useful, but I was wondering how I would go about partitioning and customizing the ‘brand’ attribute?

Let’s say I wanted my ‘brand’ in my SimpleNav be ‘ABC’ where each letter was a different color, how would I go about doing that?

Thanks,

Hey @sclavijo,

To achieve that sort of thing you will probably need to use Navbar instead of NavbarSimple, then wrap each character in a html.Span and set the colour. Here’s a simple example

import dash
import dash_bootstrap_components as dbc
import dash_html_components as html

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

app.layout = dbc.Navbar(
    dbc.Container(
        [
            dbc.NavbarBrand(
                [
                    html.Span("A", style={"color": "red"}),
                    html.Span("B", style={"color": "green"}),
                    html.Span("C", style={"color": "blue"}),
                ]
            ),
            dbc.Nav(
                [
                    dbc.NavItem(dbc.NavLink("Item 1", href="#")),
                    dbc.NavItem(dbc.NavLink("Item 2", href="#")),
                ],
                navbar=True,
            ),
        ]
    )
)


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

There’s a bunch more Navbar examples here.

The reason you’ll struggle to do the same with NavbarSimple is that (currently at least), you can only pass dash components to the children prop of other dash components, so you wouldn’t be able to use html.Span like above with the brand prop. The only alternative would be if it’s possible to write CSS to cycle through colours each character, but that sounds pretty nasty to me and might not be possible anyway.

Hope that helps.

2 Likes

@sriotti and anyone else interested: I finally added some simple multi-page examples to our repo like I’ve been promising for a long time. Check them out here. They include a navbar example, plus multiple sidebar examples, including collapsible submenus and responsive designs. Try running them or check out some screenshots on the pull request.

Also more generally, the release of Dash 0.41.0 let us add some cool new features. Personally I’m pretty excited about the new Modal component, which lets you easily add modals to your apps without having to fiddle around with CSS and z-indexes. Check out the steadily improving documentation or our repo to see the new stuff we’re adding.

6 Likes

@tcbegley Great work Tom. Really appreciate the time and effort you have put into dbc. I look forward to using these new components and am excited to see what’s next!

1 Like