Loading
Page or container loading indicators.
| Class name | Type | |
|---|---|---|
.prs-loading |
Component | Container |
.prs-loading-reverse |
Modifier | Light on dark |
.prs-loading-xs |
Modifier | Size |
.prs-loading-sm |
Modifier | Size |
.prs-loading-md |
Modifier | Size |
.prs-loading-lg |
Modifier | Size |
.prs-loading-xl |
Modifier | Size |
-
Default
Use the default SVG when placing it over a light colors background. The animation falls back to fade when reduce motion OS setting is applied.
<span class="prs-loading"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200"> <style> @scope { svg:has(.spinner) { animation: fader 2s ease infinite; } .spinner-burst { fill: #FFF; transform-origin: 100px 100px; } .spinner-center { fill: #000;} .spinner-shape-1 { fill: var(--color-1, #00BCFF); } .spinner-shape-2 { fill: var(--color-2, #FF2986); } .spinner-shape-3 { fill: var(--color-3, #0900DA); } @media (prefers-reduced-motion: no-preference) { svg:has(.spinner) { animation: none; } .spinner-burst { animation: spinner 10s linear infinite; } } @keyframes spinner { from { transform: rotate(0deg); } to { transform: rotate(360deg); } } @keyframes fader { 50% { opacity: 0.5; } } } </style> <defs> <mask id="spinner-mask"> <polygon class="spinner-burst" points="200 103.43 199.98 96.06 132.69 96.23 198.26 81.09 196.6 73.91 131.03 89.05 191.59 59.7 188.37 53.07 127.82 82.42 180.32 40.33 175.71 34.59 123.21 76.67 165.03 23.96 159.26 19.38 117.44 72.09 146.48 11.39 139.83 8.21 110.79 68.91 125.6 3.27 118.41 1.65 103.6 67.29 103.43 0 96.06 .02 96.23 67.31 81.09 1.74 73.91 3.4 89.05 68.97 59.7 8.41 53.07 11.63 82.42 72.18 40.33 19.68 34.59 24.29 76.67 76.79 23.96 34.97 19.38 40.74 72.09 82.56 11.39 53.52 8.21 60.17 68.91 89.21 3.27 74.4 1.65 81.59 67.29 96.4 0 96.57 .02 103.94 67.31 103.77 1.74 118.91 3.4 126.09 68.97 110.95 8.41 140.3 11.63 146.93 72.18 117.58 19.68 159.67 24.29 165.42 76.79 123.33 34.97 176.04 40.74 180.62 82.56 127.91 53.52 188.61 60.17 191.79 89.21 131.09 74.4 196.73 81.59 198.35 96.4 132.71 96.57 200 103.94 199.98 103.77 132.69 118.91 198.26 126.09 196.6 110.95 131.03 140.3 191.59 146.93 188.37 117.58 127.82 159.67 180.32 165.41 175.71 123.33 123.21 176.04 165.03 180.62 159.26 127.91 117.44 188.61 146.48 191.79 139.83 131.09 110.79 196.73 125.6 198.35 118.41 132.71 103.6 200 103.43" /> <circle class="spinner-center" cx="100" cy="100" r="36" /> </mask> </defs> <g class="spinner" mask="url(#spinner-mask)"> <path class="spinner-shape-1" d="M69.13,24.54c-28.53,7.23-53.33,125.75-16.96,142.83,37.3,17.52,98.5-4.67,111.3-39.04,15.97-42.87-68.32-110.39-94.34-103.79Z" /> <path class="spinner-shape-2" d="M134.03,159.16s-23.38,11.77-42.45-2.6c-19.06-14.37-141.52-88.35-19.47-107.14,26.27-4.05,32.13-31.14,73.35-16.7,25.79,9.04,44.25,102.01-11.43,126.44Z" /> <path class="spinner-shape-3" d="M163.47,128.33c12.23-31.33-28.29-73.76-61.41-93.56-9.4,5.42-17.32,12.7-29.95,14.65-10.41,1.6-19.03,3.61-26.1,5.94-6.24,16.2-10.65,36.53-11.75,55.54,18.72,20.34,48.67,39.14,57.32,45.66,19.06,14.37,42.45,2.6,42.45,2.6,1.03-.45,2.03-.93,3.01-1.43,12.43-7.74,21.97-17.95,26.43-29.4Z" /> </g> </svg> </span> -
Full Working Example (dark background)
Toggle the button to see a full working example with transition and styles applied. Please use the
--prs-c-gray-900color to to 80% opacity and abackdrop-filter: blur(8px);as well ascursor: waiton a backdrop overlay. The status panel should fade in and then out for 500ms each.Make sure to adjust the status text to indicate what we are waiting for.
<div x-data=" { saving: false, flash(duration = 500) { this.saving = true setTimeout(() => { this.saving = false }, duration) }, } "> <button @click="flash(5000)" class="prs-btn prs-btn-primary">Save</button> <!-- ⚠️ notice the aria attributes ⚠️ --> <div role="status" aria-live="polite" aria-atomic="true" x-show="saving" x-transition.opacity.duration.500ms class="backdrop-blur-sm flex items-center justify-center fixed inset-0 z-50 cursor-wait select-none before:(content-[''] [background-color:var(--prs-c-gray-900)] absolute inset-0 z-[-1] opacity-80)" x-cloak> <span class="prs-loading prs-loading-sm prs-loading-reverse"> <span class="sr-only">Saving...</span> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200"> <style> @scope { svg:has(.spinner) { animation: fader 2s ease infinite; } .spinner-burst { fill: #FFF; transform-origin: 100px 100px; } .spinner-center { fill: #000;} .spinner-shape-1 { fill: var(--color-1, #00BCFF); } .spinner-shape-2 { fill: var(--color-2, #FF2986); } .spinner-shape-3 { fill: var(--color-3, #0900DA); } @media (prefers-reduced-motion: no-preference) { svg:has(.spinner) { animation: none; } .spinner-burst { animation: spinner 10s linear infinite; } } @keyframes spinner { from { transform: rotate(0deg); } to { transform: rotate(360deg); } } @keyframes fader { 50% { opacity: 0.5; } } } </style> <defs> <mask id="spinner-mask"> <polygon class="spinner-burst" points="200 103.43 199.98 96.06 132.69 96.23 198.26 81.09 196.6 73.91 131.03 89.05 191.59 59.7 188.37 53.07 127.82 82.42 180.32 40.33 175.71 34.59 123.21 76.67 165.03 23.96 159.26 19.38 117.44 72.09 146.48 11.39 139.83 8.21 110.79 68.91 125.6 3.27 118.41 1.65 103.6 67.29 103.43 0 96.06 .02 96.23 67.31 81.09 1.74 73.91 3.4 89.05 68.97 59.7 8.41 53.07 11.63 82.42 72.18 40.33 19.68 34.59 24.29 76.67 76.79 23.96 34.97 19.38 40.74 72.09 82.56 11.39 53.52 8.21 60.17 68.91 89.21 3.27 74.4 1.65 81.59 67.29 96.4 0 96.57 .02 103.94 67.31 103.77 1.74 118.91 3.4 126.09 68.97 110.95 8.41 140.3 11.63 146.93 72.18 117.58 19.68 159.67 24.29 165.42 76.79 123.33 34.97 176.04 40.74 180.62 82.56 127.91 53.52 188.61 60.17 191.79 89.21 131.09 74.4 196.73 81.59 198.35 96.4 132.71 96.57 200 103.94 199.98 103.77 132.69 118.91 198.26 126.09 196.6 110.95 131.03 140.3 191.59 146.93 188.37 117.58 127.82 159.67 180.32 165.41 175.71 123.33 123.21 176.04 165.03 180.62 159.26 127.91 117.44 188.61 146.48 191.79 139.83 131.09 110.79 196.73 125.6 198.35 118.41 132.71 103.6 200 103.43" /> <circle class="spinner-center" cx="100" cy="100" r="36" /> </mask> </defs> <g class="spinner" mask="url(#spinner-mask)"> <path class="spinner-shape-1" d="M69.13,24.54c-28.53,7.23-53.33,125.75-16.96,142.83,37.3,17.52,98.5-4.67,111.3-39.04,15.97-42.87-68.32-110.39-94.34-103.79Z" /> <path class="spinner-shape-2" d="M134.03,159.16s-23.38,11.77-42.45-2.6c-19.06-14.37-141.52-88.35-19.47-107.14,26.27-4.05,32.13-31.14,73.35-16.7,25.79,9.04,44.25,102.01-11.43,126.44Z" /> <path class="spinner-shape-3" d="M163.47,128.33c12.23-31.33-28.29-73.76-61.41-93.56-9.4,5.42-17.32,12.7-29.95,14.65-10.41,1.6-19.03,3.61-26.1,5.94-6.24,16.2-10.65,36.53-11.75,55.54,18.72,20.34,48.67,39.14,57.32,45.66,19.06,14.37,42.45,2.6,42.45,2.6,1.03-.45,2.03-.93,3.01-1.43,12.43-7.74,21.97-17.95,26.43-29.4Z" /> </g> </svg> </span> </div> </div>
CSS
Full Library
Component Only
.prs-loading {
pointer-events: none;
aspect-ratio: 1;
vertical-align: middle;
width: calc(var(--size-selector, .625rem) * 6);
display: inline-block;
&:where(.prs-loading-reverse) svg {
--color-1: #00BCFF;
--color-2: #FF2986;
--color-3: #FFF;
}
&:where(.prs-loading-xs) {
width: calc(var(--size-selector, .625rem) * 2);
}
&:where(.prs-loading-sm) {
width: calc(var(--size-selector, .625rem) * 4);
}
&:where(.prs-loading-md) {
width: calc(var(--size-selector, .625rem) * 6);
}
&:where(.prs-loading-lg) {
width: calc(var(--size-selector, .625rem) * 8);
}
&:where(.prs-loading-xl) {
width: calc(var(--size-selector, .625rem) * 10);
}
}
Coming soon...