Orbit Dots

A classic spinning orbit, rebuilt in pure CSS. Two-dot and three-dot versions, themable via CSS variables.

Loading…
Loading…

Variants

Loading…
Loading…

Use this on your site (self-host)

  1. Create /assets/preloaders/ and save orbit-dots.css there.
  2. Add the HTML snippet where you want the spinner.
  3. Tweak --size, --speed, colors (--dot1--dot3, --ring), and variants (--ringWidth, --tilt, --persp).
HTML
<link rel="stylesheet" href="/assets/preloaders/orbit-dots.css">

<!-- Two-dot (default circle) -->
<div class="rc-orbit rc-orbit--2" role="status" aria-label="Loading"
     style="--size:88px;--speed:1400ms">
  <span class="sr-only">Loading…</span>
  <span class="ring" aria-hidden="true"></span>
  <span class="dot d1" aria-hidden="true"></span>
  <span class="dot d2" aria-hidden="true"></span>
</div>

<!-- Three-dot with thicker ring -->
<div class="rc-orbit rc-orbit--3" role="status" aria-label="Loading"
     style="--size:88px;--speed:1500ms;--ringWidth:3px;--ring:rgba(255,255,255,.25)">
  <span class="sr-only">Loading…</span>
  <span class="ring" aria-hidden="true"></span>
  <span class="dot d1" aria-hidden="true"></span>
  <span class="dot d2" aria-hidden="true"></span>
  <span class="dot d3" aria-hidden="true"></span>
</div>

<!-- Elliptical / 3D tilt -->
<div class="rc-orbit rc-orbit--2" role="status" aria-label="Loading"
     style="--size:88px;--speed:1400ms;--tilt:30deg;--persp:700px">
  <span class="sr-only">Loading…</span>
  <span class="ring" aria-hidden="true"></span>
  <span class="dot d1" aria-hidden="true"></span>
  <span class="dot d2" aria-hidden="true"></span>
</div>
CSS
/* RetroCrave — Orbit Dots (CSS-only) */
.rc-orbit{
  --size: 96px;
  --speed: 1400ms;
  --ring: rgba(255,255,255,.18);
  --ringWidth: 1px;             /* ring thickness */
  --dot1: #5ef1ff;
  --dot2: #ff6bd6;
  --dot3: #ffe66b;
  --dotSize: 12px;
  --r: calc(var(--size)/2 - var(--dotSize)/2);

  /* 3D tilt */
  --persp: 600px;
  --tilt: 0deg;                  /* set to e.g. 30deg for ellipse */

  position:relative; width:var(--size); height:var(--size);
  display:inline-grid; place-items:center;

  transform-style: preserve-3d;
  transform: perspective(var(--persp)) rotateX(var(--tilt));
  transform-origin: center;
}
.rc-orbit .ring{
  position:absolute; inset:0; border-radius:50%;
  border: var(--ringWidth) solid var(--ring);
}
.rc-orbit .dot{
  position:absolute; left:50%; top:50%;
  width:var(--dotSize); height:var(--dotSize); border-radius:50%;
  transform: rotate(0deg) translate(var(--r)) rotate(0deg);
  will-change: transform;
}
@keyframes rc-spin{ to{ transform: rotate(360deg) translate(var(--r)) rotate(-360deg); } }

/* 2-dot */
.rc-orbit--2 .d1{ background:var(--dot1); animation:rc-spin var(--speed) linear infinite; }
.rc-orbit--2 .d2{ background:var(--dot2); animation:rc-spin var(--speed) linear infinite; animation-delay: calc(var(--speed) / -2); }

/* 3-dot */
.rc-orbit--3 .d1{ background:var(--dot1); animation:rc-spin var(--speed) linear infinite; }
.rc-orbit--3 .d2{ background:var(--dot2); animation:rc-spin var(--speed) linear infinite; animation-delay: calc(var(--speed) / -3); }
.rc-orbit--3 .d3{ background:var(--dot3); animation:rc-spin var(--speed) linear infinite; animation-delay: calc(var(--speed) * -2 / 3); }

/* Reduced motion */
@media (prefers-reduced-motion: reduce){
  .rc-orbit .dot{ animation: none !important; transform: translate(-50%,-50%) !important; }
}

/* A11y helper */
.sr-only{
  position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;
  clip:rect(0,0,0,0);white-space:nowrap;border:0;
}
  • On light backgrounds, set --ring: rgba(0,0,0,.2).
  • Try --ringWidth: 2px–4px and --tilt: 20–35deg for a nice ellipse.