Spinner
Indicate the loading state of a component or page with Bootstrap spinners.
<div class="d-flex align-items-center gap-3">
<twig:Spinner color="primary" label="Loading..." />
<twig:Spinner type="grow" color="secondary" label="Loading..." />
</div>
Installation
php bin/console ux:install spinner --kit bootstrap
Install the following Composer dependencies:
composer require twig/extra-bundle twig/html-extra:^3.12.0
Install the following front-end dependencies:
npm install bootstrap@^5.3.0
# ...or with Symfony AssetMapper
php bin/console importmap:require bootstrap bootstrap/dist/css/bootstrap.min.css
Copy the following file(s) into your app:
{# @prop type 'border'|'grow' The spinner animation style. #}
{# @prop color 'primary'|'secondary'|'success'|'danger'|'warning'|'info'|'light'|'dark'|null The Bootstrap contextual text color. #}
{# @prop small boolean Whether to use Bootstrap's compact spinner size. #}
{# @prop role string|null The ARIA role used for an announced loading status. #}
{# @prop label string The visually hidden loading message. #}
{# @prop decorative boolean Whether to hide the spinner from assistive technologies. #}
{# @block content The accessible loading message or custom inner content. #}
{%- props
type = 'border',
color = null,
small = false,
role = 'status',
label = 'Loading...',
decorative = false
-%}
{%- set spinner_type = type == 'grow' ? 'grow' : 'border' -%}
{%- set spinner_classes = html_classes({
('spinner-' ~ spinner_type): true,
('spinner-' ~ spinner_type ~ '-sm'): small,
('text-' ~ color): color in ['primary', 'secondary', 'success', 'danger', 'warning', 'info', 'light', 'dark'],
}) -%}
{%- set default_attrs = {class: spinner_classes} -%}
{%- if decorative -%}
{%- set default_attrs = default_attrs|merge({'aria-hidden': 'true'}) -%}
{%- elseif role not in [null, ''] -%}
{%- set default_attrs = default_attrs|merge({role: role}) -%}
{%- endif -%}
<div {{ attributes.defaults(default_attrs) }}>
{%- block content -%}
{%- if not decorative -%}
<span class="visually-hidden">{{ label }}</span>
{%- endif -%}
{%- endblock -%}
</div>
Usage
<twig:Spinner label="Loading search results..." />
Accessibility
Standalone spinners use role="status" and include a visually hidden loading message. Customize label so the announced status describes what is loading.
When visible text already announces the status, set decorative to hide the spinner itself from assistive technologies.
Examples
Border spinner
Use the border animation for a lightweight loading indicator.
<twig:Spinner label="Loading..." />
Colors
The spinner inherits currentColor; use Bootstrap contextual text colors to customize it.
<div class="d-flex flex-wrap gap-3">
<twig:Spinner color="primary" label="Loading..." />
<twig:Spinner color="secondary" label="Loading..." />
<twig:Spinner color="success" label="Loading..." />
<twig:Spinner color="danger" label="Loading..." />
<twig:Spinner color="warning" label="Loading..." />
<twig:Spinner color="info" label="Loading..." />
<twig:Spinner color="light" label="Loading..." />
<twig:Spinner color="dark" label="Loading..." />
</div>
Growing spinner
Switch to the growing animation while keeping the same contextual color options.
<div class="d-flex flex-wrap gap-3">
<twig:Spinner type="grow" label="Loading..." />
<twig:Spinner type="grow" color="primary" label="Loading..." />
<twig:Spinner type="grow" color="secondary" label="Loading..." />
<twig:Spinner type="grow" color="success" label="Loading..." />
<twig:Spinner type="grow" color="danger" label="Loading..." />
<twig:Spinner type="grow" color="warning" label="Loading..." />
<twig:Spinner type="grow" color="info" label="Loading..." />
<twig:Spinner type="grow" color="light" label="Loading..." />
<twig:Spinner type="grow" color="dark" label="Loading..." />
</div>
Margin
Use Bootstrap spacing utilities to add space around a spinner.
<twig:Spinner class="m-5" label="Loading..." />
Flex placement
Use flexbox utilities to center a spinner or place it after a visible loading status.
<div class="d-flex flex-column gap-4">
<div class="d-flex justify-content-center">
<twig:Spinner label="Loading..." />
</div>
<div class="d-flex align-items-center">
<strong role="status">Loading...</strong>
<twig:Spinner class="ms-auto" decorative />
</div>
</div>
Floats
Use float utilities when a spinner needs to follow the edge of its container.
<div class="clearfix">
<twig:Spinner class="float-end" label="Loading..." />
</div>
Text align
Because the component is inline-flex, text alignment utilities can position it within a block.
<div class="text-center">
<twig:Spinner label="Loading..." />
</div>
Size
Use the compact Bootstrap size or set custom dimensions with CSS.
<div class="d-flex align-items-center gap-3">
<twig:Spinner small label="Loading..." />
<twig:Spinner type="grow" small label="Loading..." />
<twig:Spinner style="width: 3rem; height: 3rem" label="Loading..." />
<twig:Spinner type="grow" style="width: 3rem; height: 3rem" label="Loading..." />
</div>
Buttons
Place a decorative spinner inside a disabled button and provide the loading status as button text or visually hidden text.
<div class="d-flex flex-wrap gap-2">
<button class="btn btn-primary" type="button" disabled>
<twig:Spinner small decorative />
<span class="visually-hidden">Loading...</span>
</button>
<button class="btn btn-primary" type="button" disabled>
<twig:Spinner small decorative />
<span>Loading...</span>
</button>
<button class="btn btn-primary" type="button" disabled>
<twig:Spinner type="grow" small decorative />
<span class="visually-hidden">Loading...</span>
</button>
<button class="btn btn-primary" type="button" disabled>
<twig:Spinner type="grow" small decorative />
<span>Loading...</span>
</button>
</div>
API Reference
<twig:Spinner>
| Prop | Type | Default |
|---|---|---|
type The spinner animation style.
|
'border'|'grow' |
'border' |
color The Bootstrap contextual text color.
|
'primary'|'secondary'|'success'|'danger'|'warning'|'info'|'light'|'dark'|null |
null |
small Whether to use Bootstrap's compact spinner size.
|
boolean |
false |
role The ARIA role used for an announced loading status.
|
string|null |
'status' |
label The visually hidden loading message.
|
string |
'Loading...' |
decorative Whether to hide the spinner from assistive technologies.
|
boolean |
false |
| Block | Description |
|---|---|
content |
The accessible loading message or custom inner content. |