2026, Jan 02 11:00
Add Loading Text to Dash dcc.Loading’s Built-in Spinner with a Simple CSS ::after Rule
Learn how to add loading text to Dash dcc.Loading’s built-in spinner using className and a CSS ::after rule—no custom_spinner required. With minimal example.
When you rely on the built-in spinners in Dash dcc.Loading, you often want a short status line under the loader so users know what’s happening. Out of the box, the built-in spinner shows no text. The good news: you can add a caption without rebuilding the spinner or using custom_spinner.
Minimal example that shows the issue
The app below uses type="graph" in dcc.Loading. While data is being prepared, only the spinner appears—no text.
import time
import plotly.express as px
import dash_mantine_components as dmc
import dash
from dash import dcc, callback, Output, Input
dash.register_page(module=__name__)
layout = dmc.MantineProvider(
children=[
dmc.Select(
id="picker",
data=["bar", "scatter", "none"],
value="bar",
),
dcc.Loading(
type="graph",
children=dmc.Box(id="fig_slot")
)
]
)
@callback(
Output("fig_slot", "children"),
Input("picker", "value")
)
def render_plot(kind):
if kind == "bar":
time.sleep(5)
return dcc.Graph(figure=px.bar())
elif kind == "scatter":
time.sleep(5)
return dcc.Graph(figure=px.scatter())
else:
return []
What’s happening
dcc.Loading renders its built-in spinner, and there’s no parameter to add inline text to that spinner. However, the component exposes a className prop on the spinner’s root DOM node, which lets you target it from CSS and inject content via a pseudo-element.
className (string; optional): Additional CSS class for the built-in spinner root DOM node.
The key is to set the content of the ::after pseudo-element for that node in a CSS file located in your assets folder, so the browser renders the text below the spinner.
The fix: add className and use a CSS ::after caption
Add a className to dcc.Loading, then define the text in a stylesheet. You don’t need custom_spinner, and you don’t have to rebuild the spinner.
import time
import plotly.express as px
import dash_mantine_components as dmc
import dash
from dash import dcc, callback, Output, Input
dash.register_page(module=__name__)
layout = dmc.MantineProvider(
children=[
dmc.Select(
id="picker",
data=["bar", "scatter", "none"],
value="bar",
),
dcc.Loading(
type="graph",
className="spinner",
children=dmc.Box(id="fig_slot")
)
]
)
@callback(
Output("fig_slot", "children"),
Input("picker", "value")
)
def render_plot(kind):
if kind == "bar":
time.sleep(5)
return dcc.Graph(figure=px.bar())
elif kind == "scatter":
time.sleep(5)
return dcc.Graph(figure=px.scatter())
else:
return []
Place the following CSS in a file inside your assets folder (for example, assets/app.css):
.spinner::after {
content: "loading...";
}
Once the CSS is picked up, the loader will display the text defined in content alongside the built-in spinner.
Why this matters
This approach keeps you on the built-in dcc.Loading spinner while letting you surface contextual text. It avoids extra work with custom_spinner and keeps the implementation small and maintainable by leveraging a single className and a tiny CSS rule.
Takeaway
If you need a caption for a dcc.Loading spinner, assign a className to the component and set the caption with a ::after rule in a CSS file under your assets directory. It’s a direct, reliable way to add text without recreating the spinner or wiring up custom components.