Styling and theming

Bokeh can be used to configure various visual aspects of the diagrams.

Firstly, we make the standard imports:

[1]:
from bokeh.io import output_notebook, show
from bokeh.plotting import figure
[2]:
output_notebook()
Loading BokehJS ...

Colours

Bokeh can take on colours in different ways:

  • one of the 147 named CSS colours, for example green, indigo

  • an RGB(A) hexadecimal value, for example #FF0000, #44444444

  • a 3-tuple of integers (r,g,b) between 0 and 255

  • a 4-tuple of (r,g,b,a) where r, g and b are integers between 0 and 255 and a is a floating point value between 0 and 1

Properties

Regardless of how a bokeh plot is created, the design can always be defined by attributes for the bokeh objects that make up the resulting plot. There are three types of visual properties: line, fill and text properties. Complete information with code and examples can be found in the Styling Visual Properties section of the user manual.

Plots

Many top-level attributes of plots (outline, border etc.) can be configured. Detailed information can be found in the Plots section.

Here is an example that describes the plot frame:

[3]:
p = figure(width=400, height=400)
p.border_fill_color = "whitesmoke"
p.min_border_left = 30

p.circle([1,2,3,4,5], [2,5,8,2,7], size=10)

show(p)

Glyphs

It is also possible to design the visual properties of glyphs. If you use bokeh.plotting, this is often done when calling the glyph methods:

p.circle (line_color = "red", fill_alpha = 0,2, ...)

However, it is also possible to specify these properties directly on glyph objects. Glyph objects are found in GlyphRenderer objects that are returned by the Plot.add_glyph and bokeh.plotting methods. Let’s take a look at an example:

[4]:
p = figure(width=400, height=400)

# keep a reference to the returned GlyphRenderer
r = p.circle([1,2,3,4,5], [2,5,8,2,7])

r.glyph.size = 50
r.glyph.fill_alpha = 0.2
r.glyph.line_color = "firebrick"
r.glyph.line_dash = [5, 1]
r.glyph.line_width = 2

show(p)

selection and nonselection visuals

You can also specify how the glyphs should look. The set of selected points is designed according to the optional .selection_glyph property of a GlyphRenderer:

r.selection_glyph = Circle(fill_alpha=1, fill_color="firebrick", line_color=None)

The non-selected points can be designed with the optional .nonselection_glyph property of a GlyphRenderer:

r.nonselection_glyph = Circle(fill_alpha=0.2, fill_color="grey", line_color=None)

If you use the bokeh.plotting interface, you can pass these visual properties to the glyph methods more easily (see below). The glyph method creates the selection or non-selection glyphs and attaches them to the renderer.

[5]:
p = figure(width=400, height=400, tools="tap", title="Select a circle")
renderer = p.circle(
    [1, 2, 3, 4, 5],
    [2, 5, 8, 2, 7],
    size=50,
    # set visual properties for selected glyphs
    selection_color="firebrick",
    # set visual properties for non-selected glyphs
    nonselection_fill_alpha=0.2,
    nonselection_fill_color="grey",
    nonselection_line_color="firebrick",
    nonselection_line_alpha=1.0,
)

show(p)

It is also possible to specify the visual appearance of glyphs, for example by setting the optional hover_glyph:

r.hover_glyph = Circle(fill_alpha=1, fill_color="firebrick", line_color=None)

Or if bokeh.plotting glyph methods are used by passing hover_fill_alpha etc. to the glyph method. Let’s look at an example configured with a HoverTool for hline:

[6]:
from bokeh.models.tools import HoverTool
from bokeh.sampledata.glucose import data


subset = data.loc["2010-10-06"]

x, y = subset.index.to_series(), subset["glucose"]

# Basic plot setup
p = figure(
    width=600, height=300, x_axis_type="datetime", title="Hover over points"
)

p.line(x, y, line_dash="4 4", line_width=1, color="gray")

cr = p.circle(
    x,
    y,
    size=20,
    fill_color="grey",
    hover_fill_color="firebrick",
    fill_alpha=0.05,
    hover_alpha=0.3,
    line_color=None,
    hover_line_color="white",
)

p.add_tools(HoverTool(tooltips=None, renderers=[cr], mode="hline"))

show(p)

Axes

Next, we look at the styling of axes.

To style axes, axis objects must first be created. The easiest way is to use some convenient methods for Plot: axis, xaxis and yaxis. These methods return a list of axis objects:

>>> p.xaxis
[<bokeh.models.axes.LinearAxis at 0x106fa2390>]

However, you can set properties for all elements of the list, for example:

p.xaxis.axis_label = "Temperature"
p.axis.major_label_text_color = "orange"

Tab completion also works: For example, enter p.xaxis. in a notebook cell and then press the tab key to see a list of attributes that can be set here: tab-completion.png

Axis properties

Axis objects have many configurable properties that can be used to control most visual aspects of an axis. These can be grouped by function with a prefix:

Line Properties, for example * axis_line_width * major_tick_line_dash, major_tick_in and major_tick_out * minor_tick_line_width, minor_tick_in and minor_tick_out

Text Properties, for example * axis_label, axis_label_text_color, axis_label_standoff * major_label, major_label_text_font_size, major_label_orientation

As a simple first case, we change the orientation of the main auxiliary labels on both axes of a drawing:

[7]:
from math import pi


p = figure(width=400, height=400)
p.x([1, 2, 3, 4, 5], [2, 5, 8, 2, 7], size=10, line_width=2)

p.xaxis.major_label_orientation = pi / 4
p.yaxis.major_label_orientation = "vertical"

show(p)

The next example shows adjustments to several of the different axis properties at the same time:

[8]:
p = figure(width=400, height=400)
p.asterisk([1, 2, 3, 4, 5], [2, 5, 8, 2, 7], size=12, color="olive")

# change just some things about the x-axes
p.xaxis.axis_label = "Temp"
p.xaxis.axis_line_width = 3
p.xaxis.axis_line_color = "red"

# change just some things about the y-axes
p.yaxis.axis_label = "Pressure"
p.yaxis.major_label_text_color = "orange"
p.yaxis.major_label_orientation = "vertical"

# change things on all axes
p.axis.minor_tick_in = -3
p.axis.minor_tick_out = 6

show(p)

Configuring markers

All Bokeh axes have a formatting property whose value is a TickFormatter object that Bokeh uses to format the tick marks displayed by that axis. Bokeh configures default tick marks for numeric, date or categorical axes. However, we often want to customise the appearance of marker labels. This can be achieved by changing the properties of the default formatter selected by Bokeh or by completely replacing the formatter with a new type.

Firstly, we will now change the properties of a default formatter. The default date format is configured to display month/day when the axis is on the scale of days. If you want the year to always be displayed as well, you can change the Days property to a format that includes the year (see below).

[9]:
from math import pi

from bokeh.sampledata.glucose import data


week = data.loc["2010-10-01":"2010-10-08"]

p = figure(
    x_axis_type="datetime", title="Glocose Range", height=350, width=800
)
p.xaxis[0].formatter.days = "%d.%m.%Y"
p.xaxis.major_label_orientation = pi / 3

p.line(week.index, week.glucose)

show(p)

Further information that can be updated can be found in the DatetimeTickFormatter reference manual.

In addition to the tick formatters that Bokeh uses by default, there are others such as the NumeralTickFormatter that are explicitly configured. The following example shows how you can set a formatter for each axis:

[10]:
from bokeh.models import NumeralTickFormatter


p = figure(height=300, width=800)
p.circle([1, 2, 3, 4, 5], [2, 5, 8, 2, 7], size=10)

p.xaxis.formatter = NumeralTickFormatter(format="0.0%")
p.yaxis.formatter = NumeralTickFormatter(format="$0.00")

show(p)

There are many other ways to control tick label formatting, including the ability to provide a JavaScript snippet for arbitrary formatting in the browser. Further information can be found in Tick Label Formats.

It is also possible to specify where the tick marks are drawn. Further information can be found in the Tick Locations section of the user manual.

Grids

It is also possible to control the design of grids.

Grid properties in Bokeh have two possible prefixes:

In the first example, we deactivate the vertical grid lines (by setting the line colour to None) and make the horizontal grid light and dashed.

[11]:
p = figure(width=400, height=400)
p.circle([1, 2, 3, 4, 5], [2, 5, 8, 2, 7], size=10)

# change just some things about the x-grid
p.xgrid.grid_line_color = None

# change just some things about the y-grid
p.ygrid.grid_line_alpha = 0.5
p.ygrid.grid_line_dash = [6, 4]

show(p)

The next example shows how the band properties of a diagram can be specified:

[12]:
p = figure(width=400, height=400)
p.circle([1, 2, 3, 4, 5], [2, 5, 8, 2, 7], size=10)

# change just some things about the x-grid
p.xgrid.grid_line_color = None

# change just some things about the y-grid
p.ygrid.band_fill_alpha = 0.05
p.ygrid.band_fill_color = "olive"

show(p)