Progress Bar (Unbounded)
Progress Bar (Unbounded)
The unbounded progress bar is not tied to any progressive increments. It is basically a "busy" or "in progress" message. It will continue until it is cancelled by another event. If there is no such event, it will continue forever.
Note:
The unbounded progress bar is not keyboard-focusable, so if you want to hear it read by a screen reader, you will need to navigate to it via text navigation (down arrow key in JAWS and NVDA; Alt + right arrow in Narrator; Control + Option + Right arrow in VoiceOver)
Turn on a screen reader to experience this example in action.
Initial HTML Markup
<div id="progressbar-unbounded" class="deque-progressbar deque-progressbar-unbounded">
<progress role="progressbar"
aria-valuetext="In progress, please wait..."
aria-label="An unbounded progress bar which will run like this forever.">
</progress>
<p>
<button class="deque-button" id="start-progressbar">
Start
</button>
<button class="deque-button" id="stop-progressbar">
Stop
</button>
</p>
</div>
JavaScript
Required: The complete JavaScript file (for all patterns in the library): deque-patterns.min.js
Key parts of the JavaScript file
Note: The code below is functional only in the context of the complete JavaScript file.
In the @progressbar section:
function createProgressBar(progressBar, _ref) {
var _ref$bounded = _ref.bounded,
bounded = _ref$bounded === undefined ? false : _ref$bounded;
if (bounded) {
var minValue = progressBar.getAttribute('aria-valuemin');
var maxValue = progressBar.getAttribute('aria-valuemax');
progressBar.setAttribute('value-now', minValue);
progressBar.setAttribute('max', maxValue);
progressBar.setValue = function (v) {
if (v < minValue) {
v = minValue;
}
if (v > maxValue) {
v = maxValue;
}
var percent = parseInt(v / maxValue * 100);
progressBar.innerText = percent + '%';
progressBar.setAttribute('aria-valuenow', v);
progressBar.setAttribute('value-now', v);
progressBar.setAttribute('value', v);
};
progressBar.setValue(minValue);
}
return progressBar;
}
Required: Initialization JavaScript (with functionality specific to individual pattern instances):
var host = document.getElementById('progressbar-unbounded');
var progressBar = host.querySelector('progress');
progressBar.classList.add('deque-hidden');
var unboundedProgressBar = deque.createProgressBar(progressBar, {bounded: false});
unboundedProgressBar.id = 'unboundedProgressBar';
unboundedProgressBar.setAttribute(
'aria-label',
'An unbounded progress bar which will run like this forever.'
);
var startButton = host.querySelector('#start-progressbar');
startButton.addEventListener('click', function() {
unboundedProgressBar.classList.add('deque-progressbar');
unboundedProgressBar.classList.add('deque-progressbar-unbounded');
unboundedProgressBar.classList.remove('deque-hidden');
unboundedProgressBar.setAttribute('aria-busy', 'true');
});
var stopButton = host.querySelector('#stop-progressbar');
stopButton.addEventListener('click', function() {
unboundedProgressBar.classList.remove('deque-progressbar');
unboundedProgressBar.classList.remove('deque-progressbar-unbounded');
unboundedProgressBar.classList.add('deque-hidden');
unboundedProgressBar.setAttribute('aria-busy', 'false');
});
CSS
Required: The complete CSS file (for all patterns in the library): deque-patterns.min.css
Key styles within the CSS file (other styles may also be necessary):
.deque-progressbar[role='progressbar'] {
width: 100%;
background: #ffffff;
appearance: none;
border: 1px solid #cccccc;
min-width: 296px;
height: 4px;
display: block;
margin-top: 12px;
}
.deque-progressbar[role='progressbar'][aria-valuenow='100'] {
border: 1px solid #006cc1;
}
.deque-progressbar[role='progressbar']:indeterminate::-moz-progress-bar {
background: rgba(0, 0, 0, 0);
}
.deque-progressbar[role='progressbar']::-webkit-progress-bar {
background: rgba(0, 0, 0, 0);
}
.deque-progressbar[role='progressbar']::-webkit-progress-value {
background: #006cc1;
}
.deque-progressbar[role='progressbar']::-moz-progress-bar {
background: #006cc1;
}
.deque-progressbar[role='progressbar'] > [role='progressbar'] {
display: block;
position: relative;
background: rgba(0, 0, 0, 0.2);
min-width: 296px;
width: 100%;
height: 4px;
}
.deque-progressbar[role='progressbar'] > [role='progressbar'] > span {
display: block;
position: relative;
height: 100%;
background: #0078d7;
color: #0078d7;
}
.deque-progressbar-unbounded[role='progressbar'] {
appearance: none;
color: rgba(0, 0, 0, 0);
border: 0;
min-width: 296px;
height: 4px;
animation: move 20s linear infinite;
background: linear-gradient(to right, #006cc1 0%, rgba(255, 255, 255, 0) 50%, #006cc1 100%);
display: block;
margin-top: 12px;
}
@keyframes move {
0% {
background-position: 0 0;
}
100% {
background-position: -10000px 0;
}
}
@-webkit-keyframes move {
0% {
background-position: 0 0;
}
100% {
background-position: -10000px 0;
}
}
@-moz-keyframes move {
0% {
background-position: 0 0;
}
100% {
background-position: -10000px 0;
}
}
Implementation Instructions
Implement the Progress Bar pattern when you want to provide either a bounded or unbounded progress bar that is accessible on your web page or application.
Step 1: Add Dependencies
Add deque-patterns.min.css in the <head>
of the document.
<link rel="stylesheet" type="text/css" href="deque-patterns.min.css">
Add a script link to deque-patterns.min.js to the bottom of the page.
<script type="text/javascript" src="deque-patterns.min.js"></script>
Step 2: Add HTML
- Wrap the HTML in
<div>
container with a unique ID andclass="deque-progressbar deque-progressbar-unbounded"
, for styling purposes. - Create a
<progress>
container withrole="progressbar"
,aria-valuetext="In progress, please wait..."
, andaria-label="An unbounded progress bar which will run like this forever."
. - Add the buttons within a
<p>
container. - Create two buttons, the start button and the stop button, each within a
<button>
container withclass="deque-button"
, for styling purposes, and a unique ID.
Step 3: Add JavaScript
- Use the unique ID of progressbar container to select the
<div>
. - Select the
<progress>
container and pass it intodeque.createProgressBar()
along with a single key,bounded
. - If you want the progress bar to be unbounded, set the bounded key value to false. If bounded is false, the progress bar simply does nothing, but it can be visually animated to denote that something is in progress.
- Using their unique IDs, initialize the buttons. The example above hides the progress bar using
class="deque-hidden"
until the start button is selected. The stop button hides the pattern again.