Barber pole
React + Tailwind
const css = `
/* One stripe period measured straight up the tube: 14.142px along a 45deg gradient. */
@keyframes loader-barber-climb { to { transform: translateY(-20px); } }
.loader-barber { position: relative; display: flex; flex-direction: column; align-items: center; width: 40px; height: 104px; }
.loader-barber__finial { width: 10px; height: 10px; border-radius: 50%; background: light-dark(#5f626a, #a7abb2); box-shadow: inset -2px -2px 0 light-dark(rgba(0, 0, 0, 0.05), rgba(0, 0, 0, 0.18)); }
.loader-barber__cap { width: 32px; height: 10px; margin-top: -1px; border-radius: 16px 16px 3px 3px; background: light-dark(#6d7179, #7d8087); box-shadow: inset 0 -2px 0 light-dark(rgba(0, 0, 0, 0.06), rgba(0, 0, 0, 0.2)); }
.loader-barber__collar { width: 28px; height: 4px; border-radius: 1px; background: light-dark(#cbced3, #393c41); }
.loader-barber__tube { position: relative; width: 24px; height: 62px; overflow: hidden; background: light-dark(#ebedf0, #232529); }
.loader-barber__stripes {
position: absolute;
left: 0;
right: 0;
top: 0;
height: calc(100% + 20px);
background: repeating-linear-gradient(135deg, light-dark(#42454c, #e5e6e9) 0 4.95px, light-dark(#ebedf0, #232529) 4.95px 7.07px, light-dark(#6d7179, #7d8087) 7.07px 12.02px, light-dark(#ebedf0, #232529) 12.02px 14.142px);
animation: loader-barber-climb 0.9s linear infinite;
}
/* The round of the glass: darker at both edges, a highlight down the left. */
.loader-barber__tube::after { content: ''; position: absolute; inset: 0; box-shadow: inset 6px 0 6px -3px light-dark(rgba(0, 0, 0, 0.14), rgba(0, 0, 0, 0.45)), inset -6px 0 6px -3px light-dark(rgba(0, 0, 0, 0.14), rgba(0, 0, 0, 0.45)); }
.loader-barber__tube::before { content: ''; position: absolute; z-index: 1; top: 0; bottom: 0; left: 5px; width: 3px; border-radius: 2px; background: light-dark(#fbfcfd, #f1f2f3); opacity: 0.4; }
.loader-barber__base { width: 32px; height: 9px; border-radius: 3px 3px 14px 14px; background: light-dark(#6d7179, #7d8087); box-shadow: inset 0 2px 0 light-dark(rgba(0, 0, 0, 0.06), rgba(0, 0, 0, 0.2)); }
.loader-barber__foot { width: 14px; height: 6px; border-radius: 0 0 3px 3px; background: light-dark(#cbced3, #393c41); }
@media (prefers-reduced-motion: reduce) {
.loader-barber__stripes { animation: none; }
}
`;
export function BarberLoader() {
return (
<>
<style>
{css}
</style>
<div className="loader-barber" role="status" aria-label="Loading">
<span className="loader-barber__finial" aria-hidden="true" />
<span className="loader-barber__cap" aria-hidden="true" />
<span className="loader-barber__collar" aria-hidden="true" />
<span className="loader-barber__tube" aria-hidden="true">
<span className="loader-barber__stripes" />
</span>
<span className="loader-barber__collar" aria-hidden="true" />
<span className="loader-barber__base" aria-hidden="true" />
<span className="loader-barber__foot" aria-hidden="true" />
</div>
</>
);
}Markup where the component goes, CSS in your stylesheet. No JavaScript.
HTML
<div class="loader-barber" role="status" aria-label="Loading">
<span class="loader-barber__finial" aria-hidden="true"></span>
<span class="loader-barber__cap" aria-hidden="true"></span>
<span class="loader-barber__collar" aria-hidden="true"></span>
<span class="loader-barber__tube" aria-hidden="true">
<span class="loader-barber__stripes"></span>
</span>
<span class="loader-barber__collar" aria-hidden="true"></span>
<span class="loader-barber__base" aria-hidden="true"></span>
<span class="loader-barber__foot" aria-hidden="true"></span>
</div>CSS
/* One stripe period measured straight up the tube: 14.142px along a 45deg gradient. */
@keyframes loader-barber-climb { to { transform: translateY(-20px); } }
.loader-barber { position: relative; display: flex; flex-direction: column; align-items: center; width: 40px; height: 104px; }
.loader-barber__finial { width: 10px; height: 10px; border-radius: 50%; background: light-dark(#5f626a, #a7abb2); box-shadow: inset -2px -2px 0 light-dark(rgba(0, 0, 0, 0.05), rgba(0, 0, 0, 0.18)); }
.loader-barber__cap { width: 32px; height: 10px; margin-top: -1px; border-radius: 16px 16px 3px 3px; background: light-dark(#6d7179, #7d8087); box-shadow: inset 0 -2px 0 light-dark(rgba(0, 0, 0, 0.06), rgba(0, 0, 0, 0.2)); }
.loader-barber__collar { width: 28px; height: 4px; border-radius: 1px; background: light-dark(#cbced3, #393c41); }
.loader-barber__tube { position: relative; width: 24px; height: 62px; overflow: hidden; background: light-dark(#ebedf0, #232529); }
.loader-barber__stripes {
position: absolute;
left: 0;
right: 0;
top: 0;
height: calc(100% + 20px);
background: repeating-linear-gradient(135deg, light-dark(#42454c, #e5e6e9) 0 4.95px, light-dark(#ebedf0, #232529) 4.95px 7.07px, light-dark(#6d7179, #7d8087) 7.07px 12.02px, light-dark(#ebedf0, #232529) 12.02px 14.142px);
animation: loader-barber-climb 0.9s linear infinite;
}
/* The round of the glass: darker at both edges, a highlight down the left. */
.loader-barber__tube::after { content: ''; position: absolute; inset: 0; box-shadow: inset 6px 0 6px -3px light-dark(rgba(0, 0, 0, 0.14), rgba(0, 0, 0, 0.45)), inset -6px 0 6px -3px light-dark(rgba(0, 0, 0, 0.14), rgba(0, 0, 0, 0.45)); }
.loader-barber__tube::before { content: ''; position: absolute; z-index: 1; top: 0; bottom: 0; left: 5px; width: 3px; border-radius: 2px; background: light-dark(#fbfcfd, #f1f2f3); opacity: 0.4; }
.loader-barber__base { width: 32px; height: 9px; border-radius: 3px 3px 14px 14px; background: light-dark(#6d7179, #7d8087); box-shadow: inset 0 2px 0 light-dark(rgba(0, 0, 0, 0.06), rgba(0, 0, 0, 0.2)); }
.loader-barber__foot { width: 14px; height: 6px; border-radius: 0 0 3px 3px; background: light-dark(#cbced3, #393c41); }
@media (prefers-reduced-motion: reduce) {
.loader-barber__stripes { animation: none; }
}Goal: Create a "Barber pole" loader.
Visual behavior: A barber pole: the striped glass tube turns forever, its stripes climbing endlessly between the domed caps.
Technique:
- The stripes are a repeating-linear-gradient at 45 degrees on a layer one period taller than the tube, translated up by exactly one vertical period (20px) and repeated, so the loop is seamless.
- Inset shadows darken both edges of the tube and a narrow highlight runs down one side, so it reads as a glass cylinder. No SVG, just a few spans.
Accessibility: The root has role="status" and aria-label="Loading"; everything inside is decorative. Under prefers-reduced-motion the stripes are still.
My stack: {{USER_STACK}}
My styling: {{USER_STYLING}}
My constraints: {{USER_CONSTRAINTS}}
My colors: neutral only. Black, white and grays, no hues. Use the color values above as written, or my project's closest neutral tokens.
Return a single self-contained component. No dependencies.Goal: Create a "Barber pole" loader.
Visual behavior: A barber pole: the striped glass tube turns forever, its stripes climbing endlessly between the domed caps.
Technique:
- The stripes are a repeating-linear-gradient at 45 degrees on a layer one period taller than the tube, translated up by exactly one vertical period (20px) and repeated, so the loop is seamless.
- Inset shadows darken both edges of the tube and a narrow highlight runs down one side, so it reads as a glass cylinder. No SVG, just a few spans.
Accessibility: The root has role="status" and aria-label="Loading"; everything inside is decorative. Under prefers-reduced-motion the stripes are still.
My stack: {{USER_STACK}}
My styling: {{USER_STYLING}}
My constraints: {{USER_CONSTRAINTS}}
My colors: use my project's existing color tokens. The color values above are grayscale placeholders. Map each one by its role (surface, text, border, accent, glow) to my theme, and keep their relative lightness so contrast and the effect still read.
Return a single self-contained component. No dependencies.Paste into Claude, ChatGPT or Cursor after filling in {{USER_STACK}}, {{USER_STYLING}} and {{USER_CONSTRAINTS}}. Neutral keeps the greys you see here; Match my project asks the model to map them onto your own colour tokens.
Free to use in any project, commercial included. MIT-0, no attribution required. Licence
About this component
A barber pole: the striped glass tube turns forever, its stripes climbing endlessly between the domed caps.
- Dependencies
- None
- Difficulty
- Beginner
- Triggers
- continuous, loop, gradient
- Techniques
- gradient, keyframes, transform only
- Reduced motion
- Respected
- Theme
- Light and dark (follows your page's color-scheme)
The root has role="status" and aria-label="Loading"; everything inside is decorative. Under prefers-reduced-motion the stripes are still.