Панель загрузки

В этом шаблоне показано, как создать адаптивную к цвету и доступную панель загрузки с помощью элемента <progress> .

Полная статья · Видео на YouTube · Источник на Github

HTML

<main id="loading-zone" aria-busy="true">   <p>Loading Level</p>   <div class="card">     <label>       <span class="sr-only">Loading progress</span>       <progress          indeterminate          role="progressbar"          aria-describedby="loading-zone"         tabindex="-1"       >unknown</progress>     </label>   </div> </main>

CSS

         progress {   --_track: hsl(228 100% 90%);   --_track-size: min(10px, 1ex);   --_progress: hsl(228 100% 50%);   --_radius: 1e3px;   --_indeterminate-track: linear-gradient(to right,     var(--_track) 45%,     var(--_progress) 0%,     var(--_progress) 55%,     var(--_track) 0%   );   --_indeterminate-track-size: 225% 100%;   --_indeterminate-track-animation: progress-loading 2s infinite ease;      /*  reset  */   appearance: none;   border: none;      /*  custom style  */   position: relative;   height: var(--_track-size);   border-radius: var(--_radius);   overflow: hidden;    @media (prefers-color-scheme: dark) {     --_track: hsl(228 20% 30%);     --_progress: hsl(228 100% 75%);   }    &:focus-visible {     outline-color: var(--_progress);   }      /*  Safari/Chromium  */   &[value]::-webkit-progress-bar {     background-color: var(--_track);   }      &[value]::-webkit-progress-value {     background-color: var(--_progress);     transition: inline-size .25s ease-out;   }      /*  Firefox  */   &[value]::-moz-progress-bar {     background-color: var(--_progress);   }      /*  indeterminate  */   &:indeterminate::after {     content: "";     inset: 0;     position: absolute;     background: var(--_indeterminate-track);     background-size: var(--_indeterminate-track-size);     background-position: right;      animation: var(--_indeterminate-track-animation);   }      /*  indeterminate Safari  */   &:indeterminate::-webkit-progress-bar {     background: var(--_indeterminate-track);     background-size: var(--_indeterminate-track-size);     background-position: right;      animation: var(--_indeterminate-track-animation);   }      /*  indeterminate Firefox  */   &:indeterminate::-moz-progress-bar {     background: var(--_indeterminate-track);     background-size: var(--_indeterminate-track-size);     background-position: right;      animation: var(--_indeterminate-track-animation);   }      /*  complete  */   &:not([max])[value="1"]::before,   &[max="100"][value="100"]::before {     content: "✓";          position: absolute;     inset-block: 0;     inset-inline: auto 0;     display: flex;     align-items: center;     padding-inline-end: max(calc(var(--_track-size) / 4), 3px);      color: white;     font-size: calc(var(--_track-size) / 1.25);   } }  @keyframes progress-loading {   50% {     background-position: left;    } }         

JS

         const progress = document.querySelector('progress') const zone     = document.querySelector('#loading-zone')  const state = {   val: .1 }  const roundDecimals = (val, places) =>   +(Math.round(val + "e+" + places)  + "e-" + places)  const setProgress = () => {   // set loading zone status   zone.setAttribute('aria-busy', state.val < 1)    // clear attributes if no value to show   //  will show indeterminate state   if (state.val === null) {     progress.removeAttribute('aria-valuenow')     progress.removeAttribute('value')     progress.focus()     return   }    // round bad JS decimal math   const val = roundDecimals(state.val, 2)   const valPercent = val * 100 + "%"      // set value for screenreaders and element values   progress.value = val   progress.setAttribute('aria-valuenow', valPercent)   progress.innerText = valPercent    // focus so screenreaders hear the announced value update   progress.focus() }