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.