Loader: Bar + Percentage

An accessible, themable progress bar that eases from 0→100% (Flash vibes, modern stack).

0%

Use this on your site (self-host)

  1. Copy these to /assets/preloaders/ on your site: loader-bar.css and loader-bar.js.
  2. Add the HTML snippet where you want the loader to appear.
  3. Optional: tweak size/speed/colors with CSS variables on .rc-bar.

HTML snippet

HTML
<link rel="stylesheet" href="/assets/preloaders/loader-bar.css">
<div class="rc-bar" role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-live="polite"
     style="--bar-w:320px;--bar-h:14px;--speed:2200ms;--accent:#ff6bd6;--accent2:#5ef1ff;--accent3:#ffe66b">
  <div class="rc-fill"></div>
</div>
<div class="rc-pct">0%</div>
<script src="/assets/preloaders/loader-bar.js" defer></script>

/assets/preloaders/loader-bar.css

CSS
/* RetroCrave Loader — Bar */
:root{ --accent:#ff6bd6; --accent2:#5ef1ff; --accent3:#ffe66b }
.rc-bar{ width:var(--bar-w,320px); height:var(--bar-h,14px); border-radius:999px; position:relative;
  background:rgba(255,255,255,.10); border:1px solid rgba(255,255,255,.18); overflow:hidden }
.rc-fill{ position:absolute; inset:0 auto 0 0; width:0%;
  background:linear-gradient(90deg, var(--accent), var(--accent2) 60%, var(--accent3));
  box-shadow:0 0 18px rgba(255,107,214,.35); border-right:1px solid rgba(0,0,0,.25) }
.rc-pct{ font-variant-numeric:tabular-nums; color:#b7b9d4; font-weight:700; margin-top:.6rem }
@media (prefers-reduced-motion: reduce){ .rc-fill{ transition:none !important } }

/assets/preloaders/loader-bar.js

JS
(function(){
  var bars = document.querySelectorAll('.rc-bar');
  if(!bars.length) return;
  var reduce = window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches;
  bars.forEach(function(root){
    var fill = root.querySelector('.rc-fill');
    var pctEl = root.nextElementSibling && root.nextElementSibling.classList.contains('rc-pct') ? root.nextElementSibling : null;
    var speed = parseInt(getComputedStyle(root).getPropertyValue('--speed')) || 2000;
    if(reduce){ if(fill) fill.style.width='100%'; if(pctEl) pctEl.textContent='100%'; root.setAttribute('aria-valuenow','100'); return; }
    var start = performance.now();
    function tick(now){
      var t = Math.min(1, (now - start) / speed);
      t = 1 - Math.pow(1 - t, 3); // easeOutCubic
      var percent = Math.round(t * 100);
      if(fill) fill.style.width = percent + '%';
      if(pctEl) pctEl.textContent = percent + '%';
      root.setAttribute('aria-valuenow', String(percent));
      if (percent < 100) requestAnimationFrame(tick);
    }
    requestAnimationFrame(tick);
  });
})();