Inspired by this gif from FLRN GIF.
I tried to keep the compiled CSS small as well (only one @keyframes
, etc.).
- n = 10 # number of bars in one direction | |
.wrapper | |
- (n * 2).times do | |
.line |
$n: 10; // should be even (and the same as in the html) | |
$containerSize: 20rem; | |
$barSize: 1em / (2.5 * $n); | |
$duration: 3s; | |
html, body { height: 100%; } | |
body { | |
background: #262626; | |
color: #dcdcd2; | |
overflow: hidden; | |
*, *:before, *:after { position: absolute; } | |
} | |
.wrapper { | |
font-size: $containerSize; | |
top: 50%; left: 50%; | |
width: 1em; height: 1em; | |
margin: -.5em 0 0 -.5em; | |
overflow: hidden; | |
} | |
@keyframes anim { | |
from { transform: rotate(0deg) translateY(-.5em) rotate(0deg); } | |
75% { transform: rotate(180deg) translateY(.5em) rotate(45deg); } | |
to { transform: rotate(180deg) translateY(.5em) rotate(0deg); } | |
} | |
// We use a font-size trick to position the bars | |
// But we can't have a negative font-size | |
// So we actually split the thing in four (from the middle, going up/right/down/left) | |
$quarter: floor($n / 2); | |
.line { | |
left: 0; top: 50%; | |
width: 1em; height: $barSize; | |
margin-top: $barSize * -.5; | |
&:nth-child(n + #{$quarter + 1}) { transform: rotate(90deg); } | |
&:nth-child(n + #{2 * $quarter + 1}) { transform: rotate(180deg); } | |
&:nth-child(n + #{3 * $quarter + 1}) { transform: rotate(270deg); } | |
&:before, &:after { | |
content: ''; | |
width: 100%; height: 100%; | |
background: currentColor; | |
animation: anim $duration cubic-bezier(.74,.02,.66,.98) infinite; | |
} | |
&:after { // motion-blur | |
opacity: .15; | |
animation-delay: .025s; | |
} | |
@for $i from 0 to $quarter { | |
$p: 1 - $i / ($quarter - .5); | |
&:nth-child(#{$quarter}n + #{$i + 1}) { | |
&:before, &:after { | |
// Trick : we use font-size to know how much to translate the bar (see @keyfames) | |
font-size: $p * (1em - $barSize); | |
} | |
} | |
} | |
} |