Download Back To CSSScript.Com
A JavaScript library that provides a custom web component for displaying animated, accessible, customizable loading spinners in HTML documents.
<p style="background-color:yellow;padding:2em;margin-left:0;font-size:2em;">
<x-spinner prefix="We'll be right back ... " rotor="1" trace-color="transparent" back-color="white" color="red"></x-spinner>
</p>
<p style="color:blue; font-size:2em;">
<x-spinner prefix="Is it moving?" kerning="1ch" rotor="101" wt=".195" bgclr="gold" tclr="red" bkclr="rgba(0,55,255,.25)"></x-spinner>
</p>
<p style="font-size:2em;">
<x-spinner onclick="this.stopGo()" rotor="101" wt=".495" sp="2" tclr="rgba(255,255,0,1)" kern="1ch" suffix="Restricted"></x-spinner>
</p>
<p style="font-size:2em;">
<x-spinner onclick="this.stopGo()" rotor="101" rstyle="dotted" wt="3" sp="1" tclr="rgba(255,51,0,1)" kern="1ch" suffix="Click to Start/Stop"></x-spinner>
</p>
<p style="font-size:2.4em;color:#ff0000;">
<x-spinner color="#ff0000" rotor="101" wt="8" speed="1" direction="cw" back-color=transparent ></x-spinner>
Recording in Progress
<x-spinner color="#ff0000" rotor="0101" wt="8" speed="1" direction="cw" back-color=transparent "></x-spinner>
</p>
<div style="color:rgba(92, 51, 23, 1); font-size:2em;">
<x-spinner prefix="Research " suffix=" takes time." kern="0ch" wt=".195" speed=".75" rotor="1110" direction="cw" back-color="rgba(92, 51, 23, 0.2)" trace-color="transparent"></x-spinner>
</div>
<button type="button" onclick="
const spin6 = document.getElementById('sp6');
if (this.innerHTML === 'Chase') {
// set attributes individually with JS built-in .setAttribute
spin6.setAttribute('rotor-color', '#00dd00');
spin6.setAttribute('direction', 'cw');
spin6.setAttribute('sp', '.4');
spin6.setAttribute('wt', '3');
spin6.setAttribute('rstyle', 'dotted');
spin6.setAttribute('suf', ' Chasing!');
spin6.style.fontStyle = 'italic';
spin6.style.color = '#00dd00';
this.innerHTML = 'Scan';
} else {
// set attributes in one op with spinner's .setAttributes method
spin6.setAttributes({
color: '#ddd',
direction: 'ccw',
sp: '1.5',
wt: '8',
suf: ' Scanning...',
rstyle: 'solid',
rstatus: 'running',
rotor: '1'
});
spin6.style.fontStyle = 'normal';
spin6.style.color = '#ccc';
this.innerHTML = 'Chase';
}
// Show the rendered spinner in the console:
console.log( spin6.toString() );
">Scan</button>
<p style="font-size:4em;margin-top:0;margin-bottom:0;">
<!-- These attributes define the spinner when first loaded -->
<x-spinner id="sp6" rstatus="paused" rotor="1" color="#ddd" sp="1.5" tclr="#ccf" wt="8" dir="ccw" kern="0em" role="status" aria-wrap='true'></x-spinner><br>
</p>
<button type="button" onclick="
// Yes, start a spinner element from raw text
// Note need to use '<' instead of '<'
if (this.innerHTML == 'Search') {
let spn = `<x-spinner id='spinMe'></x-spinner>`;
document.getElementById('searching').innerHTML = spn;
const spinM = document.getElementById('spinMe');
spinM.setAttribute('sp', '.5');
spinM.setAttribute('rotor-style', 'double');
spinM.setAttribute('pre', 'Searching ... ');
spinM.setAttribute('direction', 'cw');
spinM.setAttribute('trace-color', 'transparent' );
console.log( spinM.toString() );
this.innerHTML = 'Cancel';
}
else {
document.getElementById('searching').innerHTML = ' ';
this.innerHTML = 'Search';
}
">Search</button>
<h2 id="searching" style="color:red;"> </h2>
<p style="font-size:3em;margin-top:0;margin-bottom:0;">
<button type="button" style="width:6em;" onclick="
const pausebtn = document.getElementById('pauseBtn');
pausebtn.style.visibility = 'visible';
const spng = document.getElementById('spinning');
if (this.innerHTML=='Spin It') {
const sp = new SpinnerElement( {} );
sp.id = 'thisSpinner';
spng.innerHTML = '';
spng.appendChild(sp);
sp.setAttributes({color: 'turquoise', suffix: ' Spinning', rstyle: 'double', role: 'status', 'aria-wrap': 'true' });
this.innerHTML='Stop It';
}
else {
spng.innerHTML = ' ';
pausebtn.style.visibility = 'hidden';
this.innerHTML='Spin It';
}
">Spin It</button> <button type="button" id="pauseBtn" style="visibility:hidden;width:6em;" onclick="
const sp = document.getElementById('thisSpinner');
if (!sp) {return};
if (this.innerHTML == 'Pause') {
sp.setSuffix(' Paused')
sp.pause();
this.innerHTML = 'Resume';
}
else {
sp.setSuffix(' Spinning ');
sp.go();
this.innerHTML = 'Pause';
}">Pause</button>
<span id="spinning"> </span>
</p>
<p id="pace" style="font-size:2em;">
<button type="button" onclick="
if (this.innerHTML=='Pace Me') {
this.currentSpeedIdx = 0;
this.innerHTML = 'Step';
}
const speeds = [ '0.1', '0.25', '0.5', '0.75', '1', '1.5', '2', '4', 'Reset' ];
if (getSpinner('#sp2')) { removeSpinner('#sp2') }
const sp2 = new SpinnerElement({id: 'sp2'});
appendSpinner(sp2, '#pace');
let curSpd = speeds[this.currentSpeedIdx];
if (curSpd === 'Reset') {
this.innerHTML = 'Pace Me';
removeSpinner('#sp2');
this.currentSpeedIdx = 0;
}
else {
let ss = curSpd === '1' ? '' : 's';
sp2.setAttributes({'color': 'blue', 'speed': curSpd, kern: '1ch', 'prefix': 'Rotation in', 'suffix': curSpd + ' second' + ss});
this.currentSpeedIdx += 1;
}
">Pace Me</button>
</p>
<button type="button" role='alert' style="font-weight:bold;height:1.6em;width:12ch;font-size:1.4em" onclick="
if (this.innerHTML=='Run') {
const sp = new SpinnerElement;
sp.id = 'thatSpinner';
this.innerHTML = '';
this.appendChild(sp);
sp.setAttributes({'color': 'purple', 'prefix': 'Cancel '});
}
else {
this.innerHTML='Run';
}
">Run</button>
insertSpinner(sp1,'#here1');
removeSpinner( [ sp1 | '#sp1_id' ] );
appendSpinner(sp2,'#here2');
removeSpinner( [ sp2 | '#sp2_id' ] );
sp3.show(); sp3.hide();
sp4.unveil(); sp4.veil();
sp5.run(); sp5.stop();
All of the spinners above use the same basic spinner, with font-size flexing from 2em to 3em set in the page's style sheet,
with the rotor color green inherited from the containing <div>, and the spinner's own markup specifying the light blue trace color.
The table shows how the spinner varies with different rotor types and weights,
and the buttons above change the rotor style for the whole set of spinners, which are identified in the HTML markup by the class "demoSpnr".
Here is the spinner markup for one of the spinners above:
<div style="color:green;">
<x-spinner class="demoSpnr" rtr="101" wt=".195" tclr="rgba(0,55,255,.25)"></x-spinner>
</div>
yielding:
Here is one of the buttons that sets the style of the rotors assigned the "demoSpnr" class,
using one of the spinner's built-in methods:
<button type="button" onclick="
const targetSpinners = document.querySelectorAll('.demoSpnr');
targetSpinners.forEach(spinner => {
spinner.setRotor('dotted');
});
">Dotted</button>
The defaults for spinners may be customized,
baking in your preferred attributes so it's not necessary to provide them in markup.
Unless you specify otherwise, they will still assume the color and size of the text they're embedded in, like a text character
Here is the standard spinner →
<x-spinner></x-spinner>
This page includes a script that uses the createSpinnerElement constructor
provided by spinnerComponent.js to create a second spinner
with a faster default speed and reverse direction:
<script>
createSpinnerElement('x-fast-revspinner', { speed: '.5', dir: 'ccw'});
</script>
Here is the second spinner →
<x-fast-revspinner></x-fast-revspinner>
A few of the spinners in the big table above are this type. Do you see them?
This page has another script to create a third "proprietary" spinner for the Acme company:
<script>
createSpinnerElement('acme-spnr-06', { sp: '.33', wt: '6', rtr: '101', dir: 'cw' });
</script>
The third spinner comes out like →
<acme-spnr-06></acme-spnr-06>
Naming custom spinners:
Note that the above scripts using `createSpinnerElement` add new spinner elements to the DOM; the original spinner with the tag name 'x-spinner' is still available.
HTML list elements do not accept custom web components as bullet markers.
Instead, the spinning bullets on the list above are provided by removing the list's own item markers by styling them list-style: none;,
and then inserting the custom spinner elements at the very start of each list item, just before its content.
The insertion is accomplished with a brief script triggered after full DOM load
to ensure the list is all there.
<script>
document.addEventListener('DOMContentLoaded', function() {
const listItems = document.querySelectorAll('.spin1 li');
const spinOpts = {
rtr: '101',
color: 'red',
bgclr: 'gold',
tclr: 'blue'
};
listItems.forEach(function(item) {
const spinner = new SpinnerElement( spinOpts );
item.insertAdjacentElement('afterbegin', spinner);
})
});
</script>