Web developers typically confine their business logic code into JS files, their layouts into HTML templates, and their styling into CSS files. This decoupling makes navigating and working on a code base easier.
In Bokeh, it's just as valuable to decouple the styles of your Models from the business logic that generates them. In this post, I'll share two ways I've found helpful for doing this.
You can download the Theme file here and read below about how to use it.
One solution to separating styles from implementation is to create an adjacent python module (I generally call it "styles.py") that contains dictionaries of Bokeh style properties for Models. To me, the distinction of whether something belongs in the styles dictionary or business logic is whether it's based on data. If a Glyph color is computed based on some data value, it belongs in the business logic. Otherwise, it should go in a styles dictionary. Based on that rubric, I'll even include some simple Bokeh Models like Tickers and Formatters in my styles dictionary.
The benefit of using style dictionaries is their simplicity. They make visualization code much shorter and readable because they pull out all of your styling code into a separate module. I think styles dictionaries most useful for simpler visualization, perhaps embedding a single plot within a web app.
When you set your Document's theme property, all of your custom styles are applied to the appropriate models. You can read more in the Themes documentation.
Now the Axis styles in our yaml file are applied to all Axis Models within our Document!
The styling dictionary approach seems to work best when developing via the bokeh.models API, where you're explicitly creating and adding all of your models. (You can read my previous blog post about the bokeh.models API). In the bokeh.plotting API some plot components, like axes for example, are implicitly created inside the figure method. This is where Themes may be better solution because they will automatically be applied to all relevant Models.
What if you want different styles for the same model type? It's possible to have different style dictionaries for distinct model instances (i.e. having X_AXIS_OPTS and Y_AXIS_OPTS dicts for a LinearAxis Model). Alternatively, since Themes just change the model defaults, it's possible to override the new defaults however you normally would.
Finally, Themes are easier to share with others. You should be able to download or copy and paste the Theme file from here into a local file and attach it to any visualization you already have.
If you want your HTML body (or whatever HTML element your layout is inside of) style to be visible behind your plots, set the Plot background_fill_color and border_fill_color attributes to None.
If you want to add custom CSS to your layout (i.e. in order to change the html body background color) you can specify a custom template for your Document and either inline or load your custom CSS there.