Skip to content

Instantly share code, notes, and snippets.

@octiwhale
Created July 11, 2025 05:35
Show Gist options
  • Select an option

  • Save octiwhale/53d1a4ef5eacdec92034115f1723b5f1 to your computer and use it in GitHub Desktop.

Select an option

Save octiwhale/53d1a4ef5eacdec92034115f1723b5f1 to your computer and use it in GitHub Desktop.
Canvas LMS Loaders

Canvas LMS Loaders

I created these loaders, which are identical clones of the ones used on Instructure's Canvas LMS software.

A Pen by Evan on CodePen.

License.

<h1>Canvas LMS Loaders</h1>
<div class="demo-row">
<div class="demo-item">
<span class="Loader-root Loader-xs" role="presentation">
<svg class="Loader-circle" role="img" aria-labelledby="L1" focusable="false">
<title id="L1">Loading…</title>
<g role="presentation">
<circle class="Loader-track" cx="50%" cy="50%" r="0.5em"></circle>
<circle class="Loader-spin" cx="50%" cy="50%" r="0.5em"></circle>
</g>
</svg>
</span>
<div>Extra-small</div>
</div>
<div class="demo-item">
<span class="Loader-root Loader-sm" role="presentation">
<svg class="Loader-circle" role="img" aria-labelledby="L2" focusable="false">
<title id="L2">Loading…</title>
<g role="presentation">
<circle class="Loader-track" cx="50%" cy="50%" r="1em"></circle>
<circle class="Loader-spin" cx="50%" cy="50%" r="1em"></circle>
</g>
</svg>
</span>
<div>Small</div>
</div>
<div class="demo-item">
<span class="Loader-root Loader-md" role="presentation">
<svg class="Loader-circle" role="img" aria-labelledby="L3" focusable="false">
<title id="L3">Loading…</title>
<g role="presentation">
<circle class="Loader-track" cx="50%" cy="50%" r="1.75em"></circle>
<circle class="Loader-spin" cx="50%" cy="50%" r="1.75em"></circle>
</g>
</svg>
</span>
<div>Medium</div>
</div>
<div class="demo-item">
<span class="Loader-root Loader-lg" role="presentation">
<svg class="Loader-circle" role="img" aria-labelledby="L4" focusable="false">
<title id="L4">Loading…</title>
<g role="presentation">
<circle class="Loader-track" cx="50%" cy="50%" r="2.25em"></circle>
<circle class="Loader-spin" cx="50%" cy="50%" r="2.25em"></circle>
</g>
</svg>
</span>
<div>Large</div>
</div>
</div>
/* === Keyframes === */
@keyframes Loader-rotate {
to {
transform: rotate(360deg);
}
}
@keyframes Loader-morph {
0% {
stroke-dashoffset: 190%;
}
50% {
stroke-dashoffset: 50%;
transform: rotate(90deg);
}
100% {
stroke-dashoffset: 190%;
transform: rotate(360deg);
}
}
/* === Base === */
.Loader-root {
display: inline-block;
vertical-align: middle;
position: relative;
box-sizing: border-box;
overflow: hidden;
--Loader-trackColor: #f2f4f4;
--Loader-color: #2b7abc;
--Loader-inverseColor: #2b7abc;
--Loader-xs-size: 1.5em;
--Loader-xs-border: 0.25em;
--Loader-sm-size: 3em;
--Loader-sm-border: 0.375em;
--Loader-md-size: 5em;
--Loader-md-border: 0.5em;
--Loader-lg-size: 7em;
--Loader-lg-border: 0.75em;
}
.Loader-circle {
display: block;
position: absolute;
top: 0;
left: 0;
animation: Loader-rotate 2.25s linear infinite;
}
.Loader-track,
.Loader-spin {
fill: none;
}
.Loader-track {
stroke: var(--Loader-trackColor);
}
.Loader-spin {
stroke: var(--Loader-color);
stroke-linecap: round;
}
.Loader-root:not(.ie11) .Loader-spin {
animation: Loader-morph 1.75s ease infinite;
}
.Loader-root.ie11 .Loader-spin {
stroke-dashoffset: 100%;
}
.Loader-inverse .Loader-spin {
stroke: var(--Loader-inverseColor);
}
/* === Sizes === */
.Loader-xs {
width: var(--Loader-xs-size);
height: var(--Loader-xs-size);
--Loader-width: var(--Loader-xs-border);
}
.Loader-xs .Loader-circle {
width: var(--Loader-xs-size);
height: var(--Loader-xs-size);
}
.Loader-xs .Loader-track,
.Loader-xs .Loader-spin {
stroke-width: var(--Loader-width);
}
.Loader-xs .Loader-spin {
stroke-dasharray: 3em;
transform-origin: 50% 50%;
}
.Loader-sm {
width: var(--Loader-sm-size);
height: var(--Loader-sm-size);
--Loader-width: var(--Loader-sm-border);
}
.Loader-sm .Loader-circle {
width: var(--Loader-sm-size);
height: var(--Loader-sm-size);
}
.Loader-sm .Loader-track,
.Loader-sm .Loader-spin {
stroke-width: var(--Loader-width);
stroke-dasharray: 6em;
transform-origin: 50% 50%;
}
.Loader-md {
width: var(--Loader-md-size);
height: var(--Loader-md-size);
--Loader-width: var(--Loader-md-border);
}
.Loader-md .Loader-circle {
width: var(--Loader-md-size);
height: var(--Loader-md-size);
stroke-width: var(--Loader-md-border);
}
.Loader-md .Loader-track,
.Loader-md .Loader-spin {
stroke-width: var(--Loader-width);
}
.Loader-md .Loader-spin {
stroke-dasharray: 10.5em;
transform-origin: 50% 50%;
}
.Loader-lg {
width: var(--Loader-lg-size);
height: var(--Loader-lg-size);
--Loader-width: var(--Loader-lg-border);
}
.Loader-lg .Loader-circle {
width: var(--Loader-lg-size);
height: var(--Loader-lg-size);
stroke-width: var(--Loader-lg-border);
}
.Loader-lg .Loader-track,
.Loader-lg .Loader-spin {
stroke-width: var(--Loader-width);
}
.Loader-lg .Loader-spin {
stroke-dasharray: 14em;
transform-origin: 50% 50%;
}
/* layout */
body {
font-family: sans-serif;
text-align: center;
margin: 2rem;
}
.demo-row {
display: flex;
justify-content: center;
gap: 2rem;
flex-wrap: wrap;
margin-top: 1rem;
}
.demo-item {
display: flex;
flex-direction: column;
align-items: center;
gap: 0.5rem;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment