Second factor
CSSA second credential lands beside the first and the pair merge into one seal.
- Tier
- CSS
- Dependencies
- None
- Duration
- 4 s, loops
- Categories
- Icons and micro-interactions
- Use cases
- Onboarding and setup, Security and trust
- Industries
- SaaS and software, Security and identity
- Style
- Geometric solid · none stroke
- Set
- vault
- Tags
- loopgeometricuiscale
Companion assets
The same artwork, not animated. Derived from the entry’s own resting state, so it matches exactly.
Code
animation.svg
<svg xmlns="http://www.w3.org/2000/svg" aria-labelledby="vault-mfa-title" class="pulsar pulsar-vault-mfa" data-pulsar="vault-mfa" role="img" viewBox="0 0 48 48"><title id="vault-mfa-title">Second factor</title><rect id="vault-mfa-first" width="14" height="14" x="7" y="17" fill="currentColor" rx="3"></rect><rect id="vault-mfa-second" width="14" height="14" x="27" y="17" fill="currentColor" rx="3"></rect><circle id="vault-mfa-seal" cx="24" cy="24" r="6" fill="currentColor"></circle></svg>
animation.css
/* Accent: the seal the two factors become, against the pair that carry it. */
.pulsar-vault-mfa #vault-mfa-seal {
fill: var(--pulsar-accent, currentColor);
}
/*
The two credentials converge and stay converged: they overlap into one
rounded card that the seal presses onto. Fading them out instead left the
resting frame as a lone circle, which says nothing about a second factor.
*/
.pulsar-vault-mfa #vault-mfa-second {
transform-box: view-box;
animation: vault-mfa-arrive 4000ms ease-in-out infinite;
}
@keyframes vault-mfa-arrive {
0% {
transform: translateX(24px);
opacity: 0;
animation-timing-function: cubic-bezier(0.22, 1, 0.36, 1);
}
22%,
38% {
transform: translateX(0);
opacity: 1;
animation-timing-function: cubic-bezier(0.65, 0, 0.35, 1);
}
56%,
88% {
transform: translateX(-10px);
opacity: 1;
}
96%,
100% {
transform: translateX(24px);
opacity: 0;
}
}
.pulsar-vault-mfa #vault-mfa-first {
transform-box: view-box;
animation: vault-mfa-merge 4000ms ease-in-out infinite;
}
@keyframes vault-mfa-merge {
0%,
38% {
transform: translateX(0);
animation-timing-function: cubic-bezier(0.65, 0, 0.35, 1);
}
56%,
88% {
transform: translateX(10px);
}
100% {
transform: translateX(0);
}
}
.pulsar-vault-mfa #vault-mfa-seal {
transform-box: fill-box;
transform-origin: center;
animation: vault-mfa-seal 4000ms ease-in-out infinite;
}
@keyframes vault-mfa-seal {
0%,
52% {
transform: scale(0.3);
opacity: 0;
animation-timing-function: cubic-bezier(0.34, 1.56, 0.64, 1);
}
68%,
88% {
transform: scale(1);
opacity: 1;
}
96%,
100% {
transform: scale(0.3);
opacity: 0;
}
}
@media (prefers-reduced-motion: reduce) {
.pulsar-vault-mfa #vault-mfa-second {
animation: none;
transform: translateX(-10px);
opacity: 1;
}
.pulsar-vault-mfa #vault-mfa-first {
animation: none;
transform: translateX(10px);
}
.pulsar-vault-mfa #vault-mfa-seal {
animation: none;
transform: scale(1);
opacity: 1;
}
}