Scroll Mask Tailwind CSS Utilities — Tim Wilson<br>twilson.netInstallation<br>Add this CSS to your Tailwind CSS v4 stylesheet:
/* scroll-mask utilities (https://twilson.net/scroll-mask) */
@property --scroll-mask-t-from {<br>syntax: "length-percentage>";<br>inherits: false;<br>initial-value: 100%;
@property --scroll-mask-b-from {<br>syntax: "length-percentage>";<br>inherits: false;<br>initial-value: 100%;
@property --scroll-mask-l-from {<br>syntax: "length-percentage>";<br>inherits: false;<br>initial-value: 100%;
@property --scroll-mask-r-from {<br>syntax: "length-percentage>";<br>inherits: false;<br>initial-value: 100%;
@keyframes scroll-mask-y-scroll {<br>0% {<br>--scroll-mask-t-from: 100%;<br>10%,<br>100% {<br>--scroll-mask-t-from: var(--scroll-mask-fade-from-t, 100%);<br>0%,<br>90% {<br>--scroll-mask-b-from: var(--scroll-mask-fade-from-b, 100%);<br>100% {<br>--scroll-mask-b-from: 100%;
@keyframes scroll-mask-x-scroll {<br>0% {<br>--scroll-mask-l-from: 100%;<br>10%,<br>100% {<br>--scroll-mask-l-from: var(--scroll-mask-fade-from-l, 100%);<br>0%,<br>90% {<br>--scroll-mask-r-from: var(--scroll-mask-fade-from-r, 100%);<br>100% {<br>--scroll-mask-r-from: 100%;
@supports (animation-timeline: scroll()) {<br>:where([class^="scroll-mask-"], [class*=" scroll-mask-"]) {<br>--scroll-mask-t: linear-gradient(<br>to top,<br>black,<br>black var(--scroll-mask-t-from),<br>transparent<br>);<br>--scroll-mask-b: linear-gradient(<br>to bottom,<br>black,<br>black var(--scroll-mask-b-from),<br>transparent<br>);<br>--scroll-mask-l: linear-gradient(<br>to left,<br>black,<br>black var(--scroll-mask-l-from),<br>transparent<br>);<br>--scroll-mask-r: linear-gradient(<br>to right,<br>black,<br>black var(--scroll-mask-r-from),<br>transparent<br>);<br>mask-image:<br>var(--scroll-mask-t), var(--scroll-mask-b), var(--scroll-mask-l),<br>var(--scroll-mask-r);<br>mask-composite: intersect;<br>-webkit-mask-composite: source-in;<br>animation:<br>scroll-mask-y-scroll linear,<br>scroll-mask-x-scroll linear;<br>animation-timeline: scroll(self block), scroll(self inline);
@utility scroll-mask-t {<br>--scroll-mask-fade-from-t: 80%;
@utility scroll-mask-t-from-* {<br>--scroll-mask-fade-from-t: --spacing(--value(integer));<br>--scroll-mask-fade-from-t: --value(percentage);<br>--scroll-mask-fade-from-t: --value([length], [percentage]);
@utility scroll-mask-b {<br>--scroll-mask-fade-from-b: 80%;
@utility scroll-mask-b-from-* {<br>--scroll-mask-fade-from-b: --spacing(--value(integer));<br>--scroll-mask-fade-from-b: --value(percentage);<br>--scroll-mask-fade-from-b: --value([length], [percentage]);
@utility scroll-mask-y {<br>--scroll-mask-fade-from-t: 80%;<br>--scroll-mask-fade-from-b: 80%;
@utility scroll-mask-y-from-* {<br>--scroll-mask-fade-from-t: --spacing(--value(integer));<br>--scroll-mask-fade-from-t: --value(percentage);<br>--scroll-mask-fade-from-t: --value([length], [percentage]);<br>--scroll-mask-fade-from-b: --spacing(--value(integer));<br>--scroll-mask-fade-from-b: --value(percentage);<br>--scroll-mask-fade-from-b: --value([length], [percentage]);
@utility scroll-mask-l {<br>--scroll-mask-fade-from-l: 80%;
@utility scroll-mask-l-from-* {<br>--scroll-mask-fade-from-l: --spacing(--value(integer));<br>--scroll-mask-fade-from-l: --value(percentage);<br>--scroll-mask-fade-from-l: --value([length], [percentage]);
@utility scroll-mask-r {<br>--scroll-mask-fade-from-r: 80%;
@utility scroll-mask-r-from-* {<br>--scroll-mask-fade-from-r: --spacing(--value(integer));<br>--scroll-mask-fade-from-r: --value(percentage);<br>--scroll-mask-fade-from-r: --value([length], [percentage]);
@utility scroll-mask-x {<br>--scroll-mask-fade-from-l: 80%;<br>--scroll-mask-fade-from-r: 80%;
@utility scroll-mask-x-from-* {<br>--scroll-mask-fade-from-l: --spacing(--value(integer));<br>--scroll-mask-fade-from-l: --value(percentage);<br>--scroll-mask-fade-from-l: --value([length], [percentage]);<br>--scroll-mask-fade-from-r: --spacing(--value(integer));<br>--scroll-mask-fade-from-r: --value(percentage);<br>--scroll-mask-fade-from-r: --value([length], [percentage]);
Copy<br>show all 166 lines
Axes<br>The axis utilities fade either end of the axis depending on scroll position: scroll-mask-y for vertical overflow, scroll-mask-x for horizontal.
Ganymede01<br>Titan02<br>Callisto03<br>Io04<br>Luna05<br>Europa06<br>Triton07<br>Titania08<br>Oberon09<br>Rhea10<br>Iapetus11<br>Charon12<br>Umbriel13<br>Ariel14<br>Dione15<br>Tethys16
scroll-mask-yanimation-timeline<br>mask-image<br>linear-gradient<br>@property<br>@keyframes<br>@utility<br>intersect<br>composite
scroll-mask-x
Masking edges<br>The four directional utilities fade a single edge.
Ganymede01<br>Titan02<br>Callisto03<br>Io04<br>Luna05<br>Europa06<br>Triton07<br>Titania08<br>Oberon09<br>Rhea10<br>Iapetus11<br>Charon12<br>Umbriel13<br>Ariel14<br>Dione15<br>Tethys16
scroll-mask-tGanymede01<br>Titan02<br>Callisto03<br>Io04<br>Luna05<br>Europa06<br>Triton07<br>Titania08<br>Oberon09<br>Rhea10<br>Iapetus11<br>Charon12<br>Umbriel13<br>Ariel14<br>Dione15<br>Tethys16
scroll-mask-banimation-timeline<br>mask-image<br>linear-gradient<br>@property<br>@keyframes<br>@utility<br>intersect<br>composite
scroll-mask-lanimation-timeline<br>mask-image<br>linear-gradient<br>@property<br>@keyframes<br>@utility<br>intersect<br>composite
scroll-mask-r
Custom stops<br>The -from-* suffix mirrors Tailwind’s mask-* family. The value is the opaque-stop position, so from-90% fades the gradient from 90% to 100% near the masked...