Plotly, Dash, Style Comps¶
Ch 03 - Plotly¶
Plotly Express and Pandas
Plotly Express and Pandas¶
Before beginning to graph with Plotly, we need to import Plotly Express!
Plotly Express is a high-level wrapper that allows for the creation of simple visualizations with minimal lines of code. It has numerous features, yet is still intuitive and consistent in terms of the syntax used across multiple chart types.
To import the library, we run the following line:
import plotly.express as px
Next, we need to import the Pandas library.
Pandas allows for the creation of dataframes, structured storage systems that integrate easily with Plotly Express. These dataframes can be thought of as data tables or spreadsheets.
To import the library, we run the following line:
import pandas as pd
And that's it!
Bar Charts
Bar Charts¶
There are a few options to create a bar chart!
Loading Data¶
With DataFrame
When creating a bar chart, we can use a Pandas Dataframe:
raw_data = {
'Animals' : ['Chicken', 'Buffalo', 'Octopus', 'Duck', 'Lion'],
'Counts' : [2, 4, 8, 4, 2]
}
df = pd.DataFrame.from_dict(raw_data)
bar = px.bar(raw_data, x='Animals', y='Counts')
bar.show()
As seen, we pass in the dataframe and specify the x and y column titles.
Without DataFrame
Here, we can simply pass in two arrays, one for each of x and y.
animals = ['Chicken', 'Buffalo', 'Octopus', 'Duck', 'Lion']
counts = [2, 4, 8, 4, 2]
bar = px.bar(x=animals, y=counts)
bar.show()
Even if we don't create a dataframe, Plotly will perform this action under-the-hood when generating the bar chart.
In both cases, we get the same result. And voila, here are our two bar charts!


Ahh, you may have noticed a small difference: the axis labels!
When we passed in two arrays, we never specified what the axes were to be titled. How do we fix this and further style our charts? To that, we turn to Plotly's myriad ways of customizing charts.
Styling Figure¶
There are many ways to style a bar chart. Here are some of the most important ones!
Adding a Title, Axis Labels
We can add a title with the following function, bar.update_layout()
:
animals = ['Chicken', 'Buffalo', 'Octopus', 'Duck', 'Lion']
counts = [2, 4, 8, 2, 4]
bar = px.bar(x=animals, y=counts)
bar.update_layout(
title="Animals vs. Appendages", # Adding a title
xaxis_title="The Amazing Animals", # Changing x-axis label
yaxis_title="How many appendages?", # Changing y-axis label
font=dict(
family="Courier New, monospace", # The font style
color="RebeccaPurple", # The font color
size=18 # The font size
)
)
bar.show()

Adding Color
In order to individually select colors for our bar chart, we can use the following:
animals = ['Chicken', 'Buffalo', 'Octopus', 'Duck', 'Lion']
counts = [2, 4, 8, 2, 4]
# As seen, each bar segment that hasn't had a discrete color entered will be shown in black
bar = px.bar(x=animals, y=counts, color_discrete_sequence=[['#65ff31', '#4a4aff', '#aa00aa']])
bar.show()

We can also use the following argument to make each column visually represent its value.
raw_data = {
'Animals' : ['Chicken', 'Buffalo', 'Octopus', 'Duck', 'Lion'],
'Counts' : [2, 4, 8, 2, 4]
}
df = pd.DataFrame.from_dict(raw_data)
# Creates a side color chart --> each color represents count
bar = px.bar(df, x='Animals', y='Counts', color='Counts')
bar.show()

As seen, it's just a matter of adding the "color" argument!
Changing Orientation
In order to make the bar chart horizontal, we can simply add the orientation='h'
argument.
animals = ['Chicken', 'Buffalo', 'Octopus', 'Duck', 'Lion']
counts = [2, 4, 8, 2, 4]
# Notice that we've had to switch the axes!
bar = px.bar(x=counts, y=animals, orientation='h')
bar.show()

NOTE: As mentioned in the above comments, we've had to switch the axes in this horizontal layout!
Width and Height
These can be easily changed via the width
and height
keywords.
animals = ['Chicken', 'Buffalo', 'Octopus', 'Duck', 'Lion']
counts = [2, 4, 8, 2, 4]
bar = px.bar(x=animals, y=counts, width=800, height=400)
bar.show()

All Put Together
Using these elements, we can create the following bar chart:
raw_data = {
'Animals' : ['Chicken', 'Buffalo', 'Octopus', 'Duck', 'Lion'],
'Counts' : [2, 4, 8, 2, 4]
}
df = pd.DataFrame.from_dict(raw_data)
bar = px.bar(df, x='Counts', y='Animals', orientation='h', color='Counts', width=800, height=400)
bar.update_layout(
title="Animals vs. Appendages", # Adding a title
yaxis_title="The Amazing Animals", # Changing x-axis label
xaxis_title="How many appendages?", # Changing y-axis label
font=dict(
family="Courier New, monospace", # The font style
color="RebeccaPurple", # The font color
size=18 # The font size
)
)
bar.show()

NOTE: For more information, make sure to check out the following: Plotly Bar Charts, px.Bar()
Line Charts
Line Charts¶
There are a few options to create a line chart!
Loading Data¶
Once again, we can either use a Pandas Dataframe or just proceed with arrays!
With DataFrame
raw_data = {
'Year' : [1980, 1985, 1990, 1995, 2000, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2018],
'Carbon per Capita' : [20.8, 18.9, 19.3, 19.3, 20.2, 18.5, 17.2, 17.4, 17.0, 16.3, 16.3, 16.5, 16.3, 16.1]
}
df = pd.DataFrame.from_dict(raw_data)
line = px.line(df, x='Year', y='Carbon per Capita')
line.show()
As seen, we pass in the dataframe and specify the x and y column titles.
Without DataFrame
Here, we can simply pass in two arrays, one for each of x and y.
year = [1980, 1985, 1990, 1995, 2000, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2018]
carbon = [20.8, 18.9, 19.3, 19.3, 20.2, 18.5, 17.2, 17.4, 17.0, 16.3, 16.3, 16.5, 16.3, 16.1]
line = px.line(x=year, y=carbon)
line.show()
Even if we don't create a dataframe, Plotly will perform this action under-the-hood when generating the line chart.
In both cases, we get the same result. And voila, here are our two line charts!


Styling Figure¶
The methods to style a line chart are very similar to styling a bar chart! However, one neat feature we haven't covered yet is traces. These are quite effective at visualizing multiple sets of data on the same set of axes.
Let's take a closer look!
Multiple Traces
In order to add multiple traces, we turn to the Plotly Graph Objects library.
To import this library, we use the following line:
import plotly.graph_objects as go
Next, we can create our traces with the .add_trace()
function.
year = [1980, 1985, 1990, 1995, 2000, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2018]
carbon_USA = [20.8, 18.9, 19.3, 19.3, 20.2, 18.5, 17.2, 17.4, 17.0, 16.3, 16.3, 16.5, 16.3, 16.1]
carbon_AUS = [15.0, 15.3, 15.5, 15.6, 17.2, 18.2, 18.2, 17.7, 17.5, 17.1, 16.1, 15.4, 16.9, 16.8]
line = go.Figure()
line.add_trace(go.Scatter(x=year, y=carbon_USA))
line.add_trace(go.Scatter(x=year, y=carbon_AUS))
line.show()
go.Scatter()
is a bit misleading!)

Styling Traces
In order to style these traces and change their legend names from 't', we can add the following:
year = [1980, 1985, 1990, 1995, 2000, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2018]
carbon_USA = [20.8, 18.9, 19.3, 19.3, 20.2, 18.5, 17.2, 17.4, 17.0, 16.3, 16.3, 16.5, 16.3, 16.1]
carbon_AUS = [15.0, 15.3, 15.5, 15.6, 17.2, 18.2, 18.2, 17.7, 17.5, 17.1, 16.1, 15.4, 16.9, 16.8]
line = go.Figure()
line.add_trace(go.Scatter(x=year, y=carbon_USA, marker = dict(color='MediumPurple'), name="USA Carbon Emissions (per capita)"))
line.add_trace(go.Scatter(x=year, y=carbon_AUS, marker = dict(color='LightSeaGreen'), name="AUS Carbon Emissions (per capita)"))
line.show()
Adding the marker=dict(color='MediumPurple')
dictionary allows us to change the color of the two traces.
Additionally, the name
argument lets us distinguish and label the two traces. Here's the result!

We can further style these traces by exploring the marker
dictionary:
year = [1980, 1985, 1990, 1995, 2000, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2018]
carbon_USA = [20.8, 18.9, 19.3, 19.3, 20.2, 18.5, 17.2, 17.4, 17.0, 16.3, 16.3, 16.5, 16.3, 16.1]
carbon_AUS = [15.0, 15.3, 15.5, 15.6, 17.2, 18.2, 18.2, 17.7, 17.5, 17.1, 16.1, 15.4, 16.9, 16.8]
line = go.Figure()
line.add_trace(go.Scatter(x=year, y=carbon_USA,
marker = dict(size=25, color='MediumPurple'),
name="USA Carbon Emissions (per capita)"))
line.add_trace(go.Scatter(x=year, y=carbon_AUS,
marker = dict(size=25, color='LightSeaGreen', symbol='square'),
name="AUS Carbon Emissions (per capita)"))
line.show()
As seen below, the size and symbols for each trace can be customized as well!

All Put Together
Using these elements and our stylings from the previous section, we can create the following:
year = [1980, 1985, 1990, 1995, 2000, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2018]
carbon_USA = [20.8, 18.9, 19.3, 19.3, 20.2, 18.5, 17.2, 17.4, 17.0, 16.3, 16.3, 16.5, 16.3, 16.1]
carbon_AUS = [15.0, 15.3, 15.5, 15.6, 17.2, 18.2, 18.2, 17.7, 17.5, 17.1, 16.1, 15.4, 16.9, 16.8]
line = go.Figure()
line.add_trace(go.Scatter(x=year, y=carbon_USA,
marker = dict(size=25, color='MediumPurple'),
name="USA Carbon Emissions (per capita)"))
line.add_trace(go.Scatter(x=year, y=carbon_AUS,
marker = dict(size=25, color='LightSeaGreen', symbol='square'),
name="AUS Carbon Emissions (per capita)"))
line.update_layout(
title = "Carbon Emissions since 1980 (per capita)",
xaxis_title = "Year",
yaxis_title = "Annual Emissions in Tons (per capita)",
plot_bgcolor = 'DarkGrey',
width=1600
)
line.show()

NOTE: For more information, make sure to check out the following: Plotly Line Charts, px.line()
Pie Charts
Pie Charts¶
There are a few options to create a pie chart!
Loading Data¶
When creating a bar chart, we can use a Pandas Dataframe:
raw_data = {
'Animals' : ['Chicken', 'Buffalo', 'Octopus', 'Duck', 'Lion', 'Horse', 'Pig'],
'Counts' : [9, 3, 1, 5, 4, 8, 8]
}
df = pd.DataFrame.from_dict(raw_data)
pie = px.pie(raw_data, values='Counts', names='Animals')
pie.show()
As seen, we pass in the dataframe and specify the x and y column titles.
Without DataFrame
Here, we can simply pass in two arrays, one for each of x and y.
animals = ['Chicken', 'Buffalo', 'Octopus', 'Duck', 'Lion', 'Horse', 'Pig']
counts = [9, 3, 1, 5, 4, 8, 8]
pie = px.pie(values=counts, names=animals)
pie.show()
Even if we don't create a dataframe, Plotly will perform this action under-the-hood when generating the pie chart.
In both cases, we get the same result. And voila, here are our two bar charts!


Unlike with bar charts and line charts, there are truly no differences between each!
This is mainly because there are no axes which need labelling 😅.
Styling Figure¶
There are many ways to style a bar chart. Here are some of the most important ones!
Adding Title, Labels
In order to add a title, we can simply pass in the title
argument. To change the
percentages in each slice into labels, we can use the .update_traces()
method. The
width of the plot is simply changed via the .update_layouts()
method, as done previously.
animals = ['Chicken', 'Buffalo', 'Octopus', 'Duck', 'Lion', 'Horse', 'Pig']
counts = [9, 3, 1, 5, 4, 8, 8]
pie = px.pie(values=counts,
names=animals,
title="The Animals of Old McDonald's Farm",
)
pie.update_traces(textposition='inside', textinfo='label')
pie.update_layout(width=1000)
pie.show()

The title can be centered with the title_x
argument, which ranges from 0 to 1.
Therefore, setting its value to 0.5 will result in a centered title. Additionally,
the .update_traces()
method can be modified to include percentages.
animals = ['Chicken', 'Buffalo', 'Octopus', 'Duck', 'Lion', 'Horse', 'Pig']
counts = [9, 3, 1, 5, 4, 8, 8]
pie = px.pie(values=counts,
names=animals,
title="The Animals of Old McDonald's Farm",
)
pie.update_traces(textposition='inside', textinfo='label+percent')
pie.update_layout(width=1000)
pie.update_layout(title_x=0.5)
pie.show()
And here's our centered title (relative to the pie chart).

Donuts, Slices¶
Some neat extensions of pie charts includes donuts and slices!
In order to create a donut chart, we simply need to add the hole=0.2
argument.
animals = ['Chicken', 'Buffalo', 'Octopus', 'Duck', 'Lion', 'Horse', 'Pig']
counts = [9, 3, 1, 5, 4, 8, 8]
pie = px.pie(values=counts,
names=animals,
title="The Animals of Old McDonald's Farm",
hole=0.2,
)
pie.update_traces(textposition='inside', textinfo='label+percent')
pie.update_layout(width=1000)
pie.update_layout(title_x=0.5)
pie.show()

In order to highlight specific slices or data values, we can use the pull
argument.
Here's an example highlighting the Pig slice!
animals = ['Chicken', 'Buffalo', 'Octopus', 'Duck', 'Lion', 'Horse', 'Pig']
counts = [9, 3, 1, 5, 4, 8, 8]
pie = px.pie(values=counts,
names=animals,
title="The Animals of Old McDonald's Farm",
hole=0.2,
)
pie.update_traces(textposition='inside',
textinfo='label+percent',
pull=[0,0,0,0,0,0,0.1],
)
pie.update_layout(width=1000)
pie.update_layout(title_x=0.5)
pie.show()

The length of pull
matches the length of animals
.
Similarly, each value corresponds to a
specific animal, in matching result. For example, the last element of pull
is 0.1, meaning
that the last element of animals
, 'Pig', will be pulled out by a factor of 0.1.
Let's try applying this knowledge to pull out 'Chicken' and 'Buffalo' as well!
animals = ['Chicken', 'Buffalo', 'Octopus', 'Duck', 'Lion', 'Horse', 'Pig']
counts = [9, 3, 1, 5, 4, 8, 8]
pie = px.pie(values=counts,
names=animals,
title="The Animals of Old McDonald's Farm",
hole=0.2,
)
pie.update_traces(textposition='inside',
textinfo='label+percent',
opacity=0.9,
pull=[0.2,0.3,0,0,0,0,0.1],
)
pie.update_layout(width=1000)
pie.update_layout(title_x=0.5)
pie.show()

Neat! And with that, we have a rather fancy pie chart put together in less than a dozen lines of code!
NOTE: For more information, make sure to check out the following: Plotly Pie Charts, px.Pie()
Scatter Plots
Scatter Plots¶
As with most other plots, there are a few options to create a scatter plot!
Loading Data¶
Here, we'll explore a less-common method with several Star Wars Lego Sets. Each Lego Set is stored as an array of three values: price, piece count, and VIP points. These arrays are added to a list of all eight sets.
Using two iterators, we can create a list of prices and pieces (ordered correctly).
rep_gunship = [349.99, 3292, 2275]; light_cruiser = [159.99, 1336, 1040]
bad_batch_shuttle = [99.99, 969, 650]; meditation_chamber = [69.99, 663, 455]
imperial_maurader = [39.99, 478, 260]; mandalorian_forge = [29.99, 258, 195]
a_wing = [199.99, 1672, 1300]; razor_crest = [129.99, 1023, 845]
sets = [rep_gunship, light_cruiser, bad_batch_shuttle, meditation_chamber, imperial_maurader, mandalorian_forge, a_wing, razor_crest]
price = [sets[i][0] for i in range(len(sets))]
pieces = [sets[i][1] for i in range(len(sets))]
scatter = px.scatter(x=price, y=pieces)
scatter.show()

Looking good, but let's add some style!
Styling Figure¶
Size Attribute
One neat way to flavor our scatter plots is to modify the size
attribute. Here,
we can set the size of each datapoint to match a third attribute. In this case, the
third dimension of data will be the number of VIP points earned per set.
# Lego Sets from 2021 (Price, Pieces, VIP Points)
rep_gunship = [349.99, 3292, 2275]; light_cruiser = [159.99, 1336, 1040]
bad_batch_shuttle = [99.99, 969, 650]; meditation_chamber = [69.99, 663, 455]
imperial_maurader = [39.99, 478, 260]; mandalorian_forge = [29.99, 258, 195]
a_wing = [199.99, 1672, 1300]; razor_crest = [129.99, 1023, 845]
sets = [rep_gunship, light_cruiser, bad_batch_shuttle, meditation_chamber, imperial_maurader, mandalorian_forge, a_wing, razor_crest]
price = [sets[i][0] for i in range(len(sets))]
pieces = [sets[i][1] for i in range(len(sets))]
points = [sets[i][2] for i in range(len(sets))]
scatter = px.scatter(x=price, y=pieces, size=points)
scatter.show()

And ta-da, we can easily visualize that larger sets give the most points!
Adding Color
As well as representing VIP points by size, we can also represent this data with color. We simply
need to add the color
argument inside of our px.scatter()
function.
# Lego Sets from 2021 (Price, Pieces, VIP Points)
rep_gunship = [349.99, 3292, 2275]; light_cruiser = [159.99, 1336, 1040]
bad_batch_shuttle = [99.99, 969, 650]; meditation_chamber = [69.99, 663, 455]
imperial_maurader = [39.99, 478, 260]; mandalorian_forge = [29.99, 258, 195]
a_wing = [199.99, 1672, 1300]; razor_crest = [129.99, 1023, 845]
sets = [rep_gunship, light_cruiser, bad_batch_shuttle, meditation_chamber, imperial_maurader, mandalorian_forge, a_wing, razor_crest]
price = [sets[i][0] for i in range(len(sets))]
pieces = [sets[i][1] for i in range(len(sets))]
points = [sets[i][2] for i in range(len(sets))]
scatter = px.scatter(x=price, y=pieces, size=points, color=points)
scatter.update_coloraxes(colorbar_title="VIP Points")
scatter.update_layout(width=1000) # For better view!
scatter.show()

Adding Trendline
Finally, one useful feature of px.Scatter()
is the ability to add trendlines! All it takes
is a simple trendline="ols"
, where "ols" stands for Ordinary Least Squares regression.
# Lego Sets from 2021 (Price, Pieces, VIP Points)
rep_gunship = [349.99, 3292, 2275]; light_cruiser = [159.99, 1336, 1040]
bad_batch_shuttle = [99.99, 969, 650]; meditation_chamber = [69.99, 663, 455]
imperial_maurader = [39.99, 478, 260]; mandalorian_forge = [29.99, 258, 195]
a_wing = [199.99, 1672, 1300]; razor_crest = [129.99, 1023, 845]
sets = [rep_gunship, light_cruiser, bad_batch_shuttle, meditation_chamber, imperial_maurader, mandalorian_forge, a_wing, razor_crest]
price = [sets[i][0] for i in range(len(sets))]
pieces = [sets[i][1] for i in range(len(sets))]
points = [sets[i][2] for i in range(len(sets))]
scatter = px.scatter(x=price, y=pieces, size=points, color=points, trendline="ols")
scatter.update_coloraxes(colorbar_title="VIP Points")
scatter.update_layout(width=1000) # For better view!
scatter.show()

NOTE: Non-linear regression lines can be added as well! For more information, check out: Plotly Trendlines
All Put Together
Using these elements and our stylings from the previous section, we can create the following:
# Lego Sets from 2021 (Price, Pieces, VIP Points)
rep_gunship = [349.99, 3292, 2275]; light_cruiser = [159.99, 1336, 1040]
bad_batch_shuttle = [99.99, 969, 650]; meditation_chamber = [69.99, 663, 455]
imperial_maurader = [39.99, 478, 260]; mandalorian_forge = [29.99, 258, 195]
a_wing = [199.99, 1672, 1300]; razor_crest = [129.99, 1023, 845]
sets = [rep_gunship, light_cruiser, bad_batch_shuttle, meditation_chamber, imperial_maurader, mandalorian_forge, a_wing, razor_crest]
price = [sets[i][0] for i in range(len(sets))]
pieces = [sets[i][1] for i in range(len(sets))]
points = [sets[i][2] for i in range(len(sets))]
scatter = px.scatter(x=price, y=pieces, size=points, color=points, trendline="ols")
scatter.update_coloraxes(colorbar_title="VIP Points")
scatter.update_layout(
title = "Lego Star Wars Sets (2021)",
xaxis_title = "Price (USD)",
yaxis_title = "Total Piece Count",
width=1000
)
scatter.show()

NOTE: For more information, make sure to check out the following: Plotly Scatter px.Scatter()
NOTE: All code segments from this chapter can be found in this Colab Notebook.
Ch 04 - Dash¶
Dash's Libraries
Dash's Libraries¶
To begin harnessing the power of Dash, we must import the necessary libraries
Dash Core¶
Dash's core components are a library of higher-level elements such as tables, graphs, dropdowns, inputs, and links. To use these components, we add the following line:
import dash_core_components as dcc
NOTE: For a full list of components, feel free to check out the following: Dash Core Documentation
Bootstrap¶
Dash allows for the inclusion of native Boostrap components via its Dash Boostrap library. These elements include cards, lists, badges, and more. To use these elements, we install and import the library via the following lines:
!pip install dash-bootstrap-components
import dash_bootstrap_components as dbc
NOTE: For a full list of components, feel free to check out the following: Dash Boostrap Documentation
And voila, we're good to go!
Dash Graph
Dash Graph¶
The figures made from Plotly are dazzling, but still need to be added into the dashboard!
In order to add these charts, we can utilize the dcc.Graph()
element. First, we create a function:
def getAnimalChart():
raw_data = {
'Animals' : ['Chicken', 'Buffalo', 'Octopus', 'Duck', 'Lion'],
'Counts' : [2, 4, 8, 2, 4]
}
df = pd.DataFrame.from_dict(raw_data)
bar = px.bar(df, x='Counts', y='Animals', orientation='h', color='Counts', width=800, height=400)
bar.update_layout(
title="Animals vs. Appendages", # Adding a title
yaxis_title="The Amazing Animals", # Changing x-axis label
xaxis_title="How many appendages?", # Changing y-axis label
font=dict(
family="Courier New, monospace", # The font style
color="RebeccaPurple", # The font color
size=18 # The font size
)
)
return bar
This function simply returns our finalized bar chart from the last chapter instead of displaying it.
Now, we can add a dcc.Graph()
component in our app via the following lines. And here's the result!
app = JupyterDash(__name__)
app.layout = html.Div(children=[
html.P(children="Welcome to Dash"),
dcc.Graph(id='Animal Chart', figure=getAnimalChart())
])
app.run_server(mode='external')

NOTE: The
id
attribute is optional, but it's a good practice to include a unique ID for each component. This is especially true for updating figures, which will be covered in a later chapter, "Confronted by Callbacks"
Pretty straightforward! Now, we can add our Plotly figures to our dashboard 😄 .
Dash Cards
Dash Cards¶
These graphs we have created are amazing! But not the prettiest...
With cards, any component (especially text, images, and figures) can neatly be displayed within a bounded area. These cards can be customized in terms of style, size, color, outline, and more!
Basic Elements¶
To get started, we'll create a simple card around our graph from earlier.
app = JupyterDash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP])
app.layout = html.Div(children=[
html.P(children="Welcome to Dash"),
dbc.Card([
dbc.CardBody([
html.H1("Animal Chart", className='card-title'),
html.P("This is an example graph displaying some statistics", className='card-body'),
dcc.Graph(id='Animal Chart', figure=getAnimalChart())
])
],
style={
"width":"55rem",
"margin-left":"1rem"
}
)
])
app.run_server(mode='external')
Alright, let's break it down!
At the very top, we must add the Bootstrap external stylesheet in order to utilize the Card component. This
stylesheet comes installed with the library and is accessed with external_stylesheets=[dbc.themes.BOOTSTRAP]
NOTE: We can add our own custom external stylesheets! We'll dive into this in "Sheriff Styles"
With our dbc.Card()
, we have a Card Body. this dbc.CardBody()
contains a header, paragraph, and our graph.
You may notice the className
attribute. This is a custom CSS styling that was imported from the Bootstrap stylesheet.
After this, the dbc.Card()
itself contains a style dictionary. In here, we find two attributes:
- Width - this is simply the width of the card.
rem
is simply the percentage dimension of the screen. As a result,55rem
means that the card will span 55% of the screen's width. - Margin - in particular, the left-most margin has been set to 1% of the screen's width.
margin-bottom
,margin-top
, andmargin-right
are all valid keywords that can be utilized as well to further adjust our card.
And voila, here's our result:

Let's try changing some of the colors!
Colors, Outlines¶
In order to modify the visual appearance of our cards, we can use the color
and
outline
attributes. color
allows for several pre-built options:
primary
, secondary
, info
, success
, warning
, danger
, light
, and dark
.
For example, here's what info
looks like (a light blue):
app = JupyterDash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP])
app.layout = html.Div(children=[
html.P(children="Welcome to Dash"),
dbc.Card([
dbc.CardBody([
html.H1("Animal Chart", className='card-title'),
html.P("This is an example graph displaying some statistics", className='card-body'),
dcc.Graph(id='Animal Chart', figure=getAnimalChart())
])
],
outline=True,
color='info', # Options include: primary, secondary, info, success, warning, danger, light, dark
style={
"width":"55rem",
"margin-left":"1rem"
}
)
])
app.run_server(mode='external')

We can also create a card to hold our title (looks kind of strange by itself in the top corner 😅)
app = JupyterDash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP])
app.layout = html.Div(children=[
dbc.Card([
dbc.CardBody([
html.H1("Welcome to Dash!", className='card-title'),
])
],
color='dark', # Options include: primary, secondary, info, success, warning, danger, light, dark
inverse=True,
style={
"width":"55rem",
"margin-left":"1rem",
"margin-top":"1rem",
"margin-bottom":"1rem"
}
),
dbc.Card([
dbc.CardBody([
html.H1("Animal Chart", className='card-title'),
html.P("This is an example graph displaying some statistics", className='card-body'),
dcc.Graph(id='Animal Chart', figure=getAnimalChart())
])
],
outline=True,
color='info', # Options include: primary, secondary, info, success, warning, danger, light, dark
style={
"width":"55rem",
"margin-left":"1rem"
}
)
])
app.run_server(mode='external')

There we go, much better now!
Ahh, you may have noticed the inverse
argument! Setting this to True
is
helpful when dealing with dark backgrounds as it inverts all text color to white.
As a result, we don't have to manually change the title color.
NOTE: For more information on dbc.Card(), feel free to check out the following: dbc.Card()
Now, what if we want to add multiple cards, but not just continue to vertically stack them?
For that, we must turn to rows and columns!
Dash Layout
Dash Layout¶
The best way to arrange components in our dashboard is via dbc.Row()
and dbc.Col()
.
Let's take a closer look at their power!
Creating Cards¶
Before beginning, let's create a few cards for better readability:
titleCard = dbc.Card([
dbc.CardBody([
html.H1("Welcome to Dash!", className='card-title'),
])
],
color='dark', # Options include: primary, secondary, info, success, warning, danger, light, dark
inverse=True,
style={
"width":"55rem",
"margin-left":"1rem",
"margin-top":"1rem",
"margin-bottom":"1rem"
}
)
def getAnimalBarChart():
raw_data = {
'Animals' : ['Chicken', 'Buffalo', 'Octopus', 'Duck', 'Lion'],
'Counts' : [2, 4, 8, 2, 4]
}
df = pd.DataFrame.from_dict(raw_data)
bar = px.bar(df, x='Counts', y='Animals', orientation='h', color='Counts', width=800, height=400)
bar.update_layout(
title="Animals vs. Appendages", # Adding a title
yaxis_title="The Amazing Animals", # Changing x-axis label
xaxis_title="How many appendages?", # Changing y-axis label
font=dict(
family="Courier New, monospace", # The font style
color="RebeccaPurple", # The font color
size=18 # The font size
)
)
return bar
animalBarCard = dbc.Card([
dbc.CardBody([
html.H1("Animal Chart", className='card-title'),
html.P("This is an example graph displaying some statistics", className='card-body'),
dcc.Graph(id='Animal Chart', figure=getAnimalBarChart())
])
],
outline=True,
color='info', # Options include: primary, secondary, info, success, warning, danger, light, dark
style={
"width":"55rem",
"margin-left":"1rem",
"margin-bottom":"1rem"
}
)
def getCarbonLineChart():
year = [1980, 1985, 1990, 1995, 2000, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2018]
carbon_USA = [20.8, 18.9, 19.3, 19.3, 20.2, 18.5, 17.2, 17.4, 17.0, 16.3, 16.3, 16.5, 16.3, 16.1]
carbon_AUS = [15.0, 15.3, 15.5, 15.6, 17.2, 18.2, 18.2, 17.7, 17.5, 17.1, 16.1, 15.4, 16.9, 16.8]
line = go.Figure()
line.add_trace(go.Scatter(x=year, y=carbon_USA,
marker = dict(size=25, color='MediumPurple'),
name="USA Carbon Emissions (per capita)"))
line.add_trace(go.Scatter(x=year, y=carbon_AUS,
marker = dict(size=25, color='LightSeaGreen', symbol='square'),
name="AUS Carbon Emissions (per capita)"))
line.update_layout(
title = "Carbon Emissions since 1980 (per capita)",
xaxis_title = "Year",
yaxis_title = "Annual Emissions in Tons (per capita)",
plot_bgcolor = 'DarkGrey',
width=1600
)
return line
carbonLineCard = dbc.Card([
dbc.CardBody([
html.H1("Carbon Chart", className='card-title'),
html.P("This is an example graph displaying some statistics", className='card-body'),
dcc.Graph(id='Carbon Chart', figure=getCarbonLineChart())
])
],
outline=True,
color='info', # Options include: primary, secondary, info, success, warning, danger, light, dark
style={
"width":"55rem",
"margin-left":"1rem",
"margin-bottom":"1rem"
}
)
def getAnimalPieChart():
animals = ['Chicken', 'Buffalo', 'Octopus', 'Duck', 'Lion', 'Horse', 'Pig']
counts = [9, 3, 1, 5, 4, 8, 8]
pie = px.pie(values=counts,
names=animals,
title="The Animals of Old McDonald's Farm",
hole=0.2,
)
pie.update_traces(textposition='inside',
textinfo='label+percent',
opacity=0.9,
pull=[0.2,0.3,0,0,0,0,0.1],
)
pie.update_layout(width=1000)
pie.update_layout(title_x=0.5)
return pie
animalPieCard = dbc.Card([
dbc.CardBody([
html.H1("Animal Pie Chart", className='card-title'),
html.P("This is an example graph displaying some statistics", className='card-body'),
dcc.Graph(id='Animal Pie Chart', figure=getAnimalPieChart())
])
],
outline=True,
color='info', # Options include: primary, secondary, info, success, warning, danger, light, dark
style={
"width":"55rem",
"margin-left":"1rem",
"margin-bottom":"1rem"
}
)
def getLegoScatterChart():
rep_gunship = [349.99, 3292, 2275]; light_cruiser = [159.99, 1336, 1040]
bad_batch_shuttle = [99.99, 969, 650]; meditation_chamber = [69.99, 663, 455]
imperial_maurader = [39.99, 478, 260]; mandalorian_forge = [29.99, 258, 195]
a_wing = [199.99, 1672, 1300]; razor_crest = [129.99, 1023, 845]
sets = [rep_gunship, light_cruiser, bad_batch_shuttle, meditation_chamber, imperial_maurader, mandalorian_forge, a_wing, razor_crest]
price = [sets[i][0] for i in range(len(sets))]
pieces = [sets[i][1] for i in range(len(sets))]
points = [sets[i][2] for i in range(len(sets))]
scatter = px.scatter(x=price, y=pieces, size=points, color=points, trendline="ols")
scatter.update_coloraxes(colorbar_title="VIP Points")
scatter.update_layout(
title = "Lego Star Wars Sets (2021)",
xaxis_title = "Price (USD)",
yaxis_title = "Total Piece Count",
width=1000
)
return scatter
legoScatterCard = dbc.Card([
dbc.CardBody([
html.H1("Lego Scatter Chart", className='card-title'),
html.P("This is an example graph displaying some statistics", className='card-body'),
dcc.Graph(id='Lego Chart', figure=getLegoScatterChart())
])
],
outline=True,
color='info', # Options include: primary, secondary, info, success, warning, danger, light, dark
style={
"width":"55rem",
"margin-left":"1rem",
"margin-bottom":"1rem"
}
)
There we go! Now we have five variables we can use:
titleCard
, animalBarCard
, carbonLineCard
, animalPieCard
, legoScatterCard
.
Let's see what we can do using them!
dbc.Row()¶
The function dbc.Row()
allows for the creation of rows, enabling horizontal arrangement of elements.
For example, we can create two rows: one to hold our title, another to hold two charts.
app = JupyterDash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP])
app.layout = html.Div(children=[
dbc.Row([
titleCard,
],
style = {
"margin-left": "0.5rem"
}
),
dbc.Row([
animalBarCard,
carbonLineCard
],
style = {
"margin-left": "0.5rem"
}
)
])
app.run_server(mode='external')

Woah, that looks pretty good!
In order to adjust the elements of rows, we can use the justify
argument.
Possible options include: start
, center
, end
, between
, and around
. For example, here we'll
use center
for the title card and around
for the body cards.
app = JupyterDash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP])
app.layout = html.Div(children=[
dbc.Row([
titleCard,
],
justify = "center",
style = {
"margin-left": "0.5rem"
}
),
dbc.Row([
animalBarCard,
carbonLineCard
],
justify = "around",
style = {
"margin-left": "0.5rem",
"margin-right":"0.5rem"
}
)
])
app.run_server(mode='external')

Alright! That looks pretty good so far! Now, let's take a look at adding columns...
dbc.Col()¶
Let's say we want to add our Pie chart underneath our "Carbon Chart". In order to do this,
we can simply use dbc.Col
. To begin, we wrap our "Carbon Chart" in a column and
include our Pie chart as part of that column:
app = JupyterDash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP])
app.layout = html.Div(children=[
dbc.Row([
titleCard,
],
justify = "center",
style = {
"margin-left": "0.5rem"
}
),
dbc.Row([
animalBarCard,
dbc.Col([
carbonLineCard,
animalPieCard
])
],
justify = "around",
style = {
"margin-left": "0.5rem",
"margin-right":"0.5rem"
}
)
])
app.run_server(mode='external')

As seen, the row automatically expands in length in order to accommodate for the column's
vertical height. In order to adjust the column's width, we can use the width
argument.
This is a value that ranges between 0 and 12.
As a result, width=4
would lead to a column approximately ⅓ of the width of its parent element.
However, we will deal with this keyword and implement it into our dashboard in future chapters!
For now, we can create another column to store our Lego Scatter Plot.
app = JupyterDash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP])
app.layout = html.Div(children=[
dbc.Row([
titleCard,
],
justify = "center",
style = {
"margin-left": "0.5rem"
}
),
dbc.Row([
dbc.Col([
animalBarCard,
legoScatterCard,
]),
dbc.Col([
carbonLineCard,
animalPieCard
])
],
justify = "around",
style = {
"margin-left": "0.5rem",
"margin-right":"0.5rem"
}
)
])
app.run_server(mode='external')

Our dashboard already looks quite stunning. All this, in just four quick chapters 🤩😄.
Next up, a little more tidying...
NOTE: For more information on rows and columns, feel free to check out: dbc.Layout()
NOTE: All code segments from this chapter can be found in this Colab Notebook.
Ch 05 - Styling¶
Badges
Badges¶
Badges are an excellent way to better display important information, especially numbers. These elements can be accessed via the Dash Bootstrap components library and can easily be integrated into our dashboard.
Basic Badge¶
They can be used in conjunction with text, as shown below.
app = JupyterDash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP])
app.layout = html.Div(children=[
html.H1(["Number of Animals: ", dbc.Badge("4", className="ml-1")]),
html.H3(["Number of Countries: ", dbc.Badge("19", className="ml-1")]),
html.H5(["Number of Lego Sets: ", dbc.Badge("None Yet!", className="ml-1")])
])
app.run_server(mode='external')

As seen, they match the size of the preceding text automatically. Additionally,
they can include both numbers and words. When used by
themselves, they default to the normal text size of html.P()
, as shown below:
app = JupyterDash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP])
app.layout = html.Div([
dbc.Badge("Number of Animals: 4", className="ml-1")
])
app.run_server(mode='external')

Coloring¶
These badges can be colored as well. They come in a total of eight different pre-built
color options, outlined here: primary
, secondary
, success
, warning
, danger
, info
, light
.
In this example, they've all been wrapped into a row (placed side-by-side) so that the differences in colors
can easily be visualized.
app = JupyterDash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP])
colors = ['primary', 'secondary', 'success', 'warning', 'danger', 'info', 'light']
app.layout = html.Div(
dbc.Row(
[html.H1(["", dbc.Badge(value, color=value, className="ml-1")]) for value in colors] ,
style = {
"margin-left":"1rem"
}
)
)
app.run_server(mode='external')

By wrapping each in an empty html.H1()
, the size of
each badge can be easily increased (a nice little trick 😄).
Pills, Links¶
Badges can also be reshaped into pills (with ovalish corners) and have embedded links. The
pills can be set simply via pill=True
and the embedded link can be
changed via the href
argument.
app = JupyterDash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP])
app.layout = html.Div(
dbc.Row([
html.H1(["", dbc.Badge("Click Me!", color='info', pill=True, href="https://google.com", className="ml-1")])
],
style = {
"margin-left":"1rem"
}
)
)
app.run_server(mode='external')

And those are the core functionalities of badges! As we'll see in the ensuing chapter (TigerGraph Tundra), they can come in quite handy when calling attention to text-based information...
NOTE: For more information, feel free to check out the following resources: dbc.Badge()
HTML Elements
HTML Elements¶
We can further modify the layout of our dashboard, especially text, by using Dash’s HTML elements.
Centering¶
Going back to our title card from Dash's Delta, we can easily center text using html.Center()
.
titleCard = dbc.Card([
dbc.CardBody([
html.H1("Welcome to Dash!", className='card-title'),
])
],
color='dark', # Options include: primary, secondary, info, success, warning, danger, light, dark
inverse=True,
style={
"width":"55rem",
"margin-left":"1rem",
"margin-top":"1rem",
"margin-bottom":"1rem"
}
)
app = JupyterDash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP])
app.layout = html.Div([
dbc.Row([
html.Center(titleCard),
],
justify="center",
style = {
"margin-left": "0.5rem"
}
),
])
app.run_server(mode='external')

This can be used to center any component, beyond just text and cards!
Horizontal Rule (Hr)¶
The html.Hr()
function creates a thin horizontal line that stretches across the page. This
can be used to separate distinct sections from one another or for easy aesthetic design.
For example,
app = JupyterDash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP])
app.layout = html.Div([
html.Center(titleCard),
html.Hr(),
html.Center(html.P("Now, we can dive further into this topic...", style={'fontSize':20}))
])
app.run_server(mode='external')

Line Break (Br)¶
The html.Br()
function creates a small line break that can be used to separate text,
paragraphs, or components. The size of the line break can be seen below:
app = JupyterDash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP])
app.layout = html.Div([
html.Center(titleCard),
html.Hr(),
html.Center(html.P("Now, we can dive further into this topic...", style={'fontSize':20})),
html.Br(),
html.Center(html.P("Before we begin, we need to put on our thinking caps!", style={'fontSize':20}))
])
app.run_server(mode='external')


And those are the core HTML components to help with style!
dcc.Markdown()
dcc.Markdown()¶
Markdown allows for the insert of Markdown into Dash (pretty intuitive naming 😅). It's quite straightforward!
app = JupyterDash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP])
app.layout = html.Div([dbc.Col(
dcc.Markdown("""
# This is a title!
Hello There! This is in **bold** while this is in *italics*
* Neat, it's a list :)
* Woah, possible foreshadowing?
Check out [Google](https://google.com)
"""
)
)
])
app.run_server(mode='external')

In order to create a title, we can simply use the #
. Bolded text is performed using
the **
symbols, while italics are added via the *
symbol. In order to create lists,
we can use the *
symbol (asterisk with a space). Links are as simple as
adding the visible text in square brackets and placing the link itself in parenthesis.
NOTE: For more information, feel free to check out the following resources: dcc.Markdown()
List Group
List Group¶
Dash Bootstrap's List Groups allow for the creation of stylish lists with ease. These lists can be used to store information, serve as embedded links, and help users better navigate and understand the layout of one's dashboard.
To create a basic list, we use the following:
app = JupyterDash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP])
app.layout = html.Div([
dbc.ListGroup([
dbc.ListGroupItem("First is the worst!"),
dbc.ListGroupItem("Second is the best!"),
dbc.ListGroupItem("Third is the one with the Treasure Chest!")
]),
])
app.run_server(mode='external')

The dbc.ListGroup()
element simply holds different list group items.
However, this list
spans the entire width of the page (or its parent component) by default. In order to adjust
its width, we can wrap the List Group within a dbc.Col()
element from earlier.
app = JupyterDash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP])
app.layout = html.Div([dbc.Col(
dbc.ListGroup([
dbc.ListGroupItem("First is the worst!"),
dbc.ListGroupItem("Second is the best!"),
dbc.ListGroupItem("Third is the one with the Treasure Chest!")
]),
width=4
)
])
app.run_server(mode='external')

There we go, much better! Now let's add some style...
Coloring Cells¶
In order to add color to each list item, we can simply use the color
argument:
app = JupyterDash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP])
app.layout = html.Div([dbc.Col(
dbc.ListGroup([
dbc.ListGroupItem("First is the worst!", color='danger'),
dbc.ListGroupItem("Second is the best!", color="success"),
dbc.ListGroupItem("Third is the one with the Treasure Chest!", color="info")
]),
width=4
)
])
app.run_server(mode='external')

As with other bootstrap components, the pre-built color options carry over in name and hue.
Horizontal List¶
Instead of keeping each list item stacked vertically, we can also arrange them horizontally.
app = JupyterDash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP])
app.layout = html.Div([dbc.Col(
dbc.ListGroup([
dbc.ListGroupItem("First is the worst!", color='danger'),
dbc.ListGroupItem("Second is the best!", color="success"),
dbc.ListGroupItem("Third is the one with the Treasure Chest!", color="info")
],
horizontal=True
),
width=6
)
])
app.run_server(mode='external')

As seen, it's just a matter of adding the horizontal
argument to our dbc.ListGroup()
.
NOTE: For more information, feel free to check out the following resources: dbc.ListGroup()
NOTE: All code segments from this chapter can be found in this Colab Notebook.