The line fades in from left to right behind a soft, feathered edge instead of a hard wipe. A gradient mask wider than the text slides across, so there is no clip line to see.
Also known as: gradient mask text reveal, soft wipe text animation, feathered text reveal.
<div class="txt-fade-in-left-to-right">Fade into view</div>
.txt-fade-in-left-to-right {
--c: var(--txt-color, #3b82f6);
font-size: var(--txt-size, 32px);
font-family: system-ui, sans-serif;
font-weight: 700;
line-height: 1.2;
display: inline-block;
white-space: nowrap;
color: var(--c);
/* opaque, then a soft ramp, then clear; the mask is 2.5x the text width */
-webkit-mask-image: linear-gradient(90deg, #000 40%, transparent 60%);
mask-image: linear-gradient(90deg, #000 40%, transparent 60%);
-webkit-mask-size: 250% 100%;
mask-size: 250% 100%;
-webkit-mask-repeat: no-repeat;
mask-repeat: no-repeat;
-webkit-mask-position: 100% 0;
mask-position: 100% 0;
animation: txt-fade-in-left-to-right-wipe 1.4s cubic-bezier(0.4, 0, 0.2, 1) forwards;}
@keyframes txt-fade-in-left-to-right-wipe {
from { transform: translateX(-0.15em); }
to { transform: translateX(0); -webkit-mask-position: 0 0; mask-position: 0 0; }
}
@media (prefers-reduced-motion: reduce) {
.txt-fade-in-left-to-right, .txt-fade-in-left-to-right *, .txt-fade-in-left-to-right::before, .txt-fade-in-left-to-right::after, .txt-fade-in-left-to-right *::before, .txt-fade-in-left-to-right *::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
}
}--txt-color on the element or a parent.
Currently previewing #3b82f6.--txt-size. Every other dimension is in
em, so the whole thing scales together. Currently previewing 40px.transition or animation
shorthand. Staggered delays are relative, so they keep their rhythm.