DataTable Tooltips allow you to provide additional information about table
cells or headers when hovering your mouse over cells.
These properties can be used to specify DataTable
tooltips:
- tooltip
: Column based tooltip configuration applied to all rows
- tooltip_conditional
: Conditional tooltips overriding tooltip
- tooltip_data
: Statically defined tooltip for each row/column combination
- tooltip_header
: Statically defined tooltip for each header column and optionally each header row
- tooltip_delay
: Table-wide default delay before the tooltip is displayed
- tooltip_duration
: Table-wide default duration before the tooltip disappears. Set to None
to prevent the tooltip from disappearing.
See DataTable Reference for detailed descriptions.
Use tooltips on individual cells if your data is abbreviated, cut-off,
or if you’d like to display more context about your data.
This example displays the same data in the cell within the header:
from dash import Dash, dash_table
import pandas as pd
from collections import OrderedDict
data_election = OrderedDict(
[
(
"Date",
[
"July 12th, 2013 - July 25th, 2013",
"July 12th, 2013 - August 25th, 2013",
"July 12th, 2014 - August 25th, 2014",
],
),
(
"Election Polling Organization",
["The New York Times", "Pew Research", "The Washington Post"],
),
("Rep", [1, -20, 3.512]),
("Dem", [10, 20, 30]),
("Ind", [2, 10924, 3912]),
(
"Region",
[
"Northern New York State to the Southern Appalachian Mountains",
"Canada",
"Southern Vermont",
],
),
]
)
df = pd.DataFrame(data_election)
app = Dash(__name__)
app.layout = dash_table.DataTable(
data=df.to_dict('records'),
columns=[{'id': c, 'name': c} for c in df.columns],
tooltip_data=[
{
column: {'value': str(value), 'type': 'markdown'}
for column, value in row.items()
} for row in df.to_dict('records')
],
# Overflow into ellipsis
style_cell={
'overflow': 'hidden',
'textOverflow': 'ellipsis',
'maxWidth': 0,
},
tooltip_delay=0,
tooltip_duration=None
)
if __name__ == '__main__':
app.run(debug=True)
The shape of the toolip_data
is a list of dictionaries, where
each dictionary’s key matches the column.id
and each dictionary’s
value is a dict with value
& type
. Alternatively, it can be a single
value and type
will be a string instead of markdown
.
from dash import Dash, dash_table
app = Dash(__name__)
app.layout = dash_table.DataTable(
data=[
{'shop': 'Bakersfield', 'sales': 4, 'goal': 10},
{'shop': 'Berkeley', 'sales': 10, 'goal': 1},
{'shop': 'Big Bear Lake', 'sales': 5, 'goal': 4}
],
columns=[
{'id': 'shop', 'name': 'Store Location'},
{'id': 'sales', 'name': 'Sales Revenue'},
{'id': 'goal', 'name': 'Revenue Goal'},
],
tooltip_data=[
{
'shop': 'Location at Bakersfield',
'sales': '$4M in Revenue',
'goal': {'value': '6M **under** Goal', 'type': 'markdown'}
},
{
'shop': 'Location at Berkeley',
'sales': '$10M in Revenue',
'goal': {'value': '9M **over** Goal', 'type': 'markdown'}
},
{
'shop': 'Location at Big Bear Lake',
'sales': '$5M in Revenue',
'goal': {'value': '1M **over** Goal', 'type': 'markdown'}
},
],
tooltip_delay=0,
tooltip_duration=None
)
if __name__ == '__main__':
app.run(debug=True)
This example displays different content in each column than what
is displayed in the cell.
from dash import Dash, dash_table
import pandas as pd
app = Dash(__name__)
df = pd.DataFrame({
'shop': ['Bakersfield', 'Berkely', 'Big Bear Lake'],
'sales': [3, 1, 5],
'goal': [10, 1, 4],
'address': [
'3000 Mall View Road, Suite 1107\n\nBakersfield, CA\n\n93306',
'2130 Center Street, Suite 102\n\nBerkeley, CA\n\n94704',
'652 Pine Knot Avenue\n\nBig Bear Lake, CA\n\n92315'
]
})
app.layout = dash_table.DataTable(
data=df.to_dict('records'),
columns=[{'id': c, 'name': c} for c in ['shop', 'sales', 'goal']],
tooltip_data=[{
'shop': {'value': row['address'], 'type': 'markdown'},
'sales': {
'value': 'Sales were **{} {}** than the goal'.format(
str(abs(row['goal'] - row['sales'])),
'less' if row['goal'] > row['sales'] else 'more'
),
'type': 'markdown'
},
'goal': 'Goal was {}'.format(
'not achieved' if row['goal'] > row['sales'] else 'achieved'
),
} for row in df.to_dict('records')],
tooltip_delay=0,
tooltip_duration=None
)
if __name__ == '__main__':
app.run(debug=True)
If your column headers are abbreviated or cut-off
(See DataTable Width),
then place a tooltip in the header with tooltip_header
.
We recommend providing some light styling to the header to indicate that
it is “hoverable”. We use the dotted underline with text-decoration
.
This isn’t supported in IE11.
In this example, the headers are cut-off because they are too long.
Our tooltip is the original name of the column.
from dash import Dash, dash_table
import pandas as pd
from collections import OrderedDict
data_election = OrderedDict(
[
(
"Date",
[
"July 12th, 2013 - July 25th, 2013",
"July 12th, 2013 - August 25th, 2013",
"July 12th, 2014 - August 25th, 2014",
],
),
(
"Election Polling Organization",
["The New York Times", "Pew Research", "The Washington Post"],
),
("Rep", [1, -20, 3.512]),
("Dem", [10, 20, 30]),
("Ind", [2, 10924, 3912]),
(
"Region",
[
"Northern New York State to the Southern Appalachian Mountains",
"Canada",
"Southern Vermont",
],
),
]
)
df = pd.DataFrame(data_election)
app = Dash(__name__)
app.layout = dash_table.DataTable(
data=df.to_dict('records'),
columns=[{'id': c, 'name': c} for c in df.columns],
tooltip_header={i: i for i in df.columns},
# Style headers with a dotted underline to indicate a tooltip
style_header={
'textDecoration': 'underline',
'textDecorationStyle': 'dotted',
},
# Overflow into ellipsis
style_cell={
'overflow': 'hidden',
'textOverflow': 'ellipsis',
'maxWidth': 0,
},
tooltip_delay=0,
tooltip_duration=None
)
if __name__ == '__main__':
app.run(debug=True)
Alternatively, you can specify a different name within tooltip_header
or specify a subset of columns:
from dash import Dash, dash_table
import pandas as pd
from collections import OrderedDict
data_election = OrderedDict(
[
(
"Date",
[
"July 12th, 2013 - July 25th, 2013",
"July 12th, 2013 - August 25th, 2013",
"July 12th, 2014 - August 25th, 2014",
],
),
(
"Election Polling Organization",
["The New York Times", "Pew Research", "The Washington Post"],
),
("Rep", [1, -20, 3.512]),
("Dem", [10, 20, 30]),
("Ind", [2, 10924, 3912]),
(
"Region",
[
"Northern New York State to the Southern Appalachian Mountains",
"Canada",
"Southern Vermont",
],
),
]
)
df = pd.DataFrame(data_election)
app = Dash(__name__)
app.layout = dash_table.DataTable(
data=df.to_dict('records'),
columns=[{'id': c, 'name': c} for c in df.columns],
tooltip_header={
'Rep': 'Republican',
'Dem': 'Democrat',
'Ind': 'Independent',
},
# Style headers with a dotted underline to indicate a tooltip
style_header_conditional=[{
'if': {'column_id': col},
'textDecoration': 'underline',
'textDecorationStyle': 'dotted',
} for col in ['Rep', 'Dem', 'Ind']],
# Overflow into ellipsis
style_cell={
'overflow': 'hidden',
'textOverflow': 'ellipsis',
'maxWidth': 0,
},
tooltip_delay=0,
tooltip_duration=None
)
if __name__ == '__main__':
app.run(debug=True)
Note that ellipses aren’t displayed in headers. This is a bug, subscribe to
plotly/dash-table#735
for details.
If your DataTable
has multiple rows of headers, then use a list
as the value of the tooltip_header
items.
For merged cells, the values must repeat in each cell.
from dash import Dash, dash_table
app = Dash(__name__)
app.layout = dash_table.DataTable(
columns=[
{"name": ["", "Year"], "id": "year"},
{"name": ["City", "Montreal"], "id": "montreal"},
{"name": ["City", "Toronto"], "id": "toronto"},
{"name": ["City", "Ottawa"], "id": "ottawa"},
{"name": ["City", "Vancouver"], "id": "vancouver"},
{"name": ["Climate", "Temperature"], "id": "temp"},
{"name": ["Climate", "Humidity"], "id": "humidity"},
],
data=[{
"year": i, "montreal": i * 10, "toronto": i * 100,
"ottawa": i * -1, "vancouver": i * -10, "temp": i * -100,
"humidity": i * 5,
} for i in range(10)],
merge_duplicate_headers=True,
tooltip_header={
'year': ['', 'Year the measurement was taken'],
'montreal': ['Average Measurements Across City', 'Montreal, QC, Canada'],
'toronto': ['Average Measurements Across City', 'Toronto, ON, Canada'],
'ottawa': ['Average Measurements Across City', 'Ottawa, ON, Canada'],
'vancouver': ['Average Measurements Across City', 'Vancouver, BC, Canada'],
'temp': ['Average for a Year', 'Celcius'],
'humidity': ['Average for a Year', 'Percentage'],
},
style_header={
'textDecoration': 'underline',
'textDecorationStyle': 'dotted',
},
)
if __name__ == '__main__':
app.run(debug=True)
As an alternative or in addition to column header tooltips, place a
tooltip to appear on the entire column with the tooltip
property.
This can also be helpful with large tables where the user
may lose track of the column headers.
If the tooltip is specified for both headers and cells, you can use
the use_with
property instead of specifying a separate tooltip_header
and tooltip
.
from dash import Dash, dash_table
import pandas as pd
from collections import OrderedDict
data_election = OrderedDict(
[
(
"Date",
[
"July 12th, 2013 - July 25th, 2013",
"July 12th, 2013 - August 25th, 2013",
"July 12th, 2014 - August 25th, 2014",
],
),
(
"Election Polling Organization",
["The New York Times", "Pew Research", "The Washington Post"],
),
("Rep", [1, -20, 3.512]),
("Dem", [10, 20, 30]),
("Ind", [2, 10924, 3912]),
(
"Region",
[
"Northern New York State to the Southern Appalachian Mountains",
"Canada",
"Southern Vermont",
],
),
]
)
df = pd.DataFrame(data_election)
app = Dash(__name__)
app.layout = dash_table.DataTable(
data=df.to_dict('records'),
columns=[{'id': c, 'name': c} for c in df.columns],
tooltip ={i: {
'value': i,
'use_with': 'both' # both refers to header & data cell
} for i in df.columns},
# Style headers with a dotted underline to indicate a tooltip
style_header={
'textDecoration': 'underline',
'textDecorationStyle': 'dotted',
},
# Overflow into ellipsis
style_cell={
'overflow': 'hidden',
'textOverflow': 'ellipsis',
'maxWidth': 0,
},
tooltip_delay=0,
tooltip_duration=None
)
if __name__ == '__main__':
app.run(debug=True)
Tooltips can also be customized based on conditions.
The tooltip_conditional
has the same syntax as the style_data_conditional
property, see the conditional formatting
chapter for many examples.
If both tooltip_conditional
and tooltip
would display a tooltip for
a cell, the conditional tooltip takes priority. If multiple conditions match the
data row, the last match has priority.
from dash import Dash, dash_table
import pandas as pd
from collections import OrderedDict
data = OrderedDict(
[
("Date", ["2015-01-01", "2015-10-24", "2016-05-10", "2017-01-10", "2018-05-10", "2018-08-15"]),
("Region", ["Montreal", "Toronto", "New York City", "Miami", "San Francisco", "London"]),
("Temperature", [1, -20, 3.512, 4, 10423, -441.2]),
("Humidity", [10, 20, 30, 40, 50, 60]),
("Pressure", [2, 10924, 3912, -10, 3591.2, 15]),
]
)
df = pd.DataFrame(data)
app = Dash(__name__)
app.layout = dash_table.DataTable(
data=df.to_dict('records'),
columns=[{'name': i, 'id': i} for i in df.columns],
tooltip_conditional=[
{
'if': {
'filter_query': '{Region} contains "New"'
},
'type': 'markdown',
'value': 'This row is significant.'
}
],
style_data_conditional=[
{
'if': {
'filter_query': '{Region} contains "New"'
},
'backgroundColor': '#0074D9',
'color': 'white',
'textDecoration': 'underline',
'textDecorationStyle': 'dotted',
}
],
tooltip_delay=0,
tooltip_duration=None
)
if __name__ == '__main__':
app.run(debug=True)
Markdown supports images with this syntax: ![alt](src)
where alt
refers to the image’s alt text
and src
is the path to the image (the src
property).
The src
can refer to images within your project’s “assets” folder
or absolute URLs. If referring to an image in the assets
folder,
we recommend using dash.get_relative_path
so that the image URL
is correct when working locally and when deploying to Dash Enterprise.
from dash import Dash, dash_table
import dash
app = Dash(__name__)
app.layout = dash_table.DataTable(
data=[
{'shop': 'Bakersfield', 'sales': 4, 'goal': 10},
{'shop': 'Berkeley', 'sales': 10, 'goal': 1},
{'shop': 'Big Bear Lake', 'sales': 5, 'goal': 4}
],
columns=[
{'id': 'shop', 'name': 'Store Location'},
{'id': 'sales', 'name': 'Sales Revenue'},
{'id': 'goal', 'name': 'Revenue Goal'},
],
tooltip_data=[
{
'shop': {
'value': 'Location at Bakersfield\n\n![Bakersfield]({})'.format(
dash.get_relative_path('/assets/images/table/bakersfield.jpg')
),
'type': 'markdown'
}
},
{
'shop': {
'value': 'Location at Berkeley\n\n![Berkeley]({})'.format(
dash.get_relative_path('/assets/images/table/berkeley.jpg')
),
'type': 'markdown'
}
},
{
'shop': {
'value': 'Location at Big Bear Lake\n\n![Big Bear Lake](https://upload.wikimedia.org/wikipedia/commons/thumb/d/d9/Big_Bear_Valley%2C_California.jpg/1200px-Big_Bear_Valley%2C_California.jpg)',
'type': 'markdown'
}
},
],
# Style headers with a dotted underline to indicate a tooltip
style_data_conditional=[{
'if': {'column_id': 'shop'},
'textDecoration': 'underline',
'textDecorationStyle': 'dotted',
}],
tooltip_delay=0,
tooltip_duration=None
)
if __name__ == '__main__':
app.run(debug=True)
Markdown supports tables with a syntax that looks like this:
| City | Value | Return |
| :------------- | :----------: | -----------: |
| Montreal | 41,531 | 431.245 |
| Seattle | 53,153 | 12.431 |
City | Value | Return |
---|---|---|
Montreal | 41,531 | 431.245 |
Seattle | 53,153 | 12.431 |
This can be specified within a table’s value:
from dash import Dash, dash_table
app = Dash(__name__)
markdown_table = """
| City | Value | Return |
| :------------- | :----------: | -----------: |
| Montreal | 41,531 | 431.245 |
| Seattle | 53,153 | 12.431 |
"""
app.layout = dash_table.DataTable(
data=[
{'shop': 'Bakersfield', 'sales': 4, 'goal': 10},
{'shop': 'Berkeley', 'sales': 10, 'goal': 1},
{'shop': 'Big Bear Lake', 'sales': 5, 'goal': 4}
],
columns=[
{'id': 'shop', 'name': 'Store Location'},
{'id': 'sales', 'name': 'Sales Revenue'},
{'id': 'goal', 'name': 'Revenue Goal'},
],
tooltip={
c: {'value': markdown_table, 'type': 'markdown'}
for c in ['shop', 'sales', 'goal']
},
tooltip_delay=0,
tooltip_duration=None
)
if __name__ == '__main__':
app.run(debug=True)
Tooltips can be styled with the dash-tooltip
(container) and dash-table-tooltip
(content) CSS classes.
This can be specified within a CSS file inside your assets/
folder
or within the table itself with the css
property.
from dash import Dash, dash_table
import pandas as pd
from collections import OrderedDict
data = OrderedDict(
[
("Date", ["2015-01-01", "2015-10-24", "2016-05-10", "2017-01-10", "2018-05-10", "2018-08-15"]),
("Region", ["Montreal", "Toronto", "New York City", "Miami", "San Francisco", "London"]),
("Temperature", [1, -20, 3.512, 4, 10423, -441.2]),
("Humidity", [10, 20, 30, 40, 50, 60]),
("Pressure", [2, 10924, 3912, -10, 3591.2, 15]),
]
)
df = pd.DataFrame(data)
app = Dash(__name__)
app.layout = dash_table.DataTable(
data=df.to_dict('records'),
columns=[{'id': c, 'name': c} for c in df.columns],
tooltip_data=[
{
column: {'value': str(value), 'type': 'markdown'}
for column, value in row.items()
} for row in df.to_dict('records')
],
css=[{
'selector': '.dash-table-tooltip',
'rule': 'background-color: grey; font-family: monospace; color: white'
}],
tooltip_delay=0,
tooltip_duration=None
)
if __name__ == '__main__':
app.run(debug=True)
Set tooltip_delay
to 0
for the tooltips to appear immediately.
Set tooltip_duration
to None
in order for the tooltips to remain
visible while you are hovering over them. Otherwise, they will disappear
after tooltip_duration
milliseconds.