Skip to content
Snippets Groups Projects
Name Last commit Last update
src
.gitignore
LICENSE
README.md
pyproject.toml
setup.cfg

The custom CSS by department 1.7, ready to be used with bokeh applications.

How to style Bokeh Apps with CSS

This file discusses multiple ways to add custom CSS to a bokeh app, as well as helpful hints for writing the CSS file. This Repo contains a small example of how we add our CSS to our bokeh apps.

This note is based on bokeh-3.3.1.

Getting started with CSS

If you are not familiar with CSS, I recommend the following links to get started:

Adding CSS to Bokeh

There are multiple ways to add CSS styling to Bokeh:

  1. Using one or more InlineStyleSheets and/or ImportedStyleSheets to add styling to a single bokeh element. This way, the style is only added to that specific element, and it appears as a <style>-block or a <link rel="stylesheet"> in that element's html. If the element contains more elements, it is only attached to the outermost element - see nr 3 for working with shadow roots. For example:

    from bokeh.models import Div, InlineStyleSheet, ImportedStyleSheet
    from bokeh.plotting import curdoc
    
    stylesheet1 = ImportedStyleSheet(url = "https://cdn.simplecss.org/simple.min.css")
    stylesheet2 = InlineStyleSheet(css = 'div {color: red}')
    placeholderDiv = Div(text="This is the styled div", stylesheets=[stylesheet1, stylesheet2])
    curdoc().add_root(placeholderDiv)

    The resulting HTML looks something like this:

    <html lang="en">
    <head>
        ...
    </head>
    <body>
        <div ...>
            <div class="bk-Div">
                <link rel="stylesheet" href="https://cdn.simplecss.org/simple.min.css">
                <style type="text/css">div {color: red}</style>
                <div class="bk-clearfix" style="display: inline-block;">This is the styled div</div>
            </div>
        </div>  
    </body></html>
  2. Similarly to 1., adding style sheets to the root of the document is done by using one or more GlobalInlineStyleSheets and/or GlobalImportedStyleSheets. To apply them, they are attached as style sheets to any bokeh element. If you are using custom templates, adding your style sheets to the head will have the same effect. Note that they are only added in the document's <head> and as such have no effect on any bokeh element inside shadow roots. An Example:

    from bokeh.models import Div, GlobalInlineStyleSheet, GlobalImportedStyleSheet
    from bokeh.plotting import curdoc
    
    globalStylesheet1 = GlobalImportedStyleSheet(url = "https://cdn.simplecss.org/simple.min.css")
    globalStylesheet2 = GlobalInlineStyleSheet(css = 'div {color: red}')
    placeholderDiv = Div(text="This is a div", stylesheets=[globalStylesheet1, globalStylesheet2])
    curdoc().add_root(placeholderDiv)

    The resulting HTML should look something like this:

    <html lang="en">
        <head>
            <meta charset="utf-8">
            <title>Bokeh Application</title>
            <link rel="stylesheet" href="https://cdn.simplecss.org/simple.min.css">
            <style type="text/css">div {color: red}</style>
        </head>
        <body>
            <div ...>
                <div class="bk-Div">
                    This is a div
                </div>
            </div>
        </body>
    </html>

    Note that there is a bug in bokeh-3.3.1 that prevents GlobalImportedStyleSheets from working. It has been fixed and will be included in the next release.

    Since bokeh places a lot of elements in shadow roots, the styling in the <head> will not apply to them. GlobalStyleSheets are still useful to style the overall page appearance, such as side margins.

  3. If you want to add style sheets to all parts of the app, Themes are what you are looking for. Style sheets added via a theme are added to both the document's head and to every shadow root that bokeh creates, and as such are applied to every element. An example:

    from bokeh.models import InlineStyleSheet, ImportedStyleSheet
    from bokeh.plotting import curdoc
    
    stylesheet1 = ImportedStyleSheet(url = "https://cdn.simplecss.org/simple.min.css")
    stylesheet2 = InlineStyleSheet(css = 'div {color: red}')
    theme = Theme(json=dict(attrs=dict(UIElement=dict(stylesheets=[stylesheet1, stylesheet2]),),),)
    curdoc().theme = theme

Problems I ran into

While trying to style our bokeh app, I encountered a number of problems.

  • Bokeh wraps a lot of it's elements in shadow roots, so that you don't style them accidentally. That can get in the way when trying to style them on purpose. To circumvent that, I used themes.
  • Unfortunately, while you are able to pass a name to each bokeh element, it is only used in the backend and not added as an id in the frontend, making it hard to reference elements.
  • Many elements are wrapped in multiple layers of divs, it's helpful to keep that in mind when writing CSS selectors.
  • bokeh does use it's own classes that correspond to the bokeh widget type of an element, and I highly recommend using the browser's inspector to learn about those when trying to style a particular type of bokeh widget.

All in all, support for custom styling is still under development, so be sure to watch out for any changes that might happen.