<!-- info on how I built this: https://utilitybend.com/blog/stylish-holidays-creating-a-scroll-driven-christmas-tree-in-css -->
<div class="tree-wrapper">
<div class="svg-items">
<svg class="ball ball__3" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 41.48 52.64" fill="#0E7C7B">
<path class="ball__path" d="M35.46 18.32A20.046 20.046 0 0 0 25 12.33v-2.01c.37-.23.7-.56.94-.98.07-.13.11-.27.11-.42V5.56c0-.45-.37-.82-.82-.82h-1.2V4c0-1.81-1.48-3.29-3.29-3.29S17.45 2.19 17.45 4v.74h-1.2c-.45 0-.82.37-.82.82v3.36c0 .15.04.29.11.42.25.42.57.75.94.98v2.01c-4 .86-7.65 2.94-10.46 5.99C2.6 22.02.71 26.85.71 31.9c0 11.04 8.99 20.03 20.03 20.03s20.03-8.99 20.03-20.03c0-5.05-1.89-9.88-5.31-13.59Z" style="fill:none;stroke:var(--color-ball-3);stroke-miterlimit:10;stroke-width:1.42px" />
<path class="ball__inner" d="M20.74 15.23c-.47 0-.86.37-.86.83s.38.83.86.83c8.74 0 15.86 6.89 15.86 15.35s-7.11 15.35-15.86 15.35c-.47 0-.86.37-.86.83s.38.83.86.83c9.69 0 17.57-7.63 17.57-17.01s-7.88-17.01-17.57-17.01ZM16.95 15.63c-2.65.57-5.17 1.75-7.29 3.42a.81.81 0 0 0-.12 1.17c.17.2.42.31.66.31.19 0 .38-.06.54-.19 1.91-1.51 4.19-2.58 6.58-3.09.46-.1.75-.54.65-.99-.1-.45-.56-.73-1.02-.63ZM8.32 21.4a.876.876 0 0 0-1.21.12c-2.54 3.02-3.94 6.83-3.94 10.73 0 .46.38.83.86.83s.86-.37.86-.83c0-3.52 1.26-6.95 3.56-9.68a.82.82 0 0 0-.12-1.17Z" />
</svg>
<svg class="ball ball__2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 41.48 52.64" fill="#E072A4">
<path class="ball__path" d="M35.46 18.32A20.046 20.046 0 0 0 25 12.33v-2.01c.37-.23.7-.56.94-.98.07-.13.11-.27.11-.42V5.56c0-.45-.37-.82-.82-.82h-1.2V4c0-1.81-1.48-3.29-3.29-3.29S17.45 2.19 17.45 4v.74h-1.2c-.45 0-.82.37-.82.82v3.36c0 .15.04.29.11.42.25.42.57.75.94.98v2.01c-4 .86-7.65 2.94-10.46 5.99C2.6 22.02.71 26.85.71 31.9c0 11.04 8.99 20.03 20.03 20.03s20.03-8.99 20.03-20.03c0-5.05-1.89-9.88-5.31-13.59Z" style="fill:none;stroke:var(--color-ball-2);stroke-miterlimit:10;stroke-width:1.42px" />
<path class="ball__inner" d="M8.71 23.79c.16.19.4.29.65.29s.49-.11.65-.29l.87-.99c.31-.35.26-.87-.1-1.17s-.9-.25-1.21.1l-.21.24-.21-.24a.886.886 0 0 0-1.21-.1.81.81 0 0 0-.1 1.17l.87.99ZM20.86 23.79c.16.19.4.29.65.29s.49-.11.65-.29l.87-.99a.81.81 0 0 0-.1-1.17c-.36-.3-.9-.25-1.21.1l-.21.24-.21-.24a.886.886 0 0 0-1.21-.1.81.81 0 0 0-.1 1.17l.87.99ZM33.02 23.79c.16.19.4.29.65.29s.49-.11.65-.29l.87-.99a.81.81 0 0 0-.1-1.17c-.36-.3-.9-.25-1.21.1l-.21.24-.21-.24a.886.886 0 0 0-1.21-.1.81.81 0 0 0-.1 1.17l.87.99ZM10.02 41.96c-.16-.19-.4-.29-.65-.29s-.49.11-.65.29l-.87.99a.81.81 0 0 0 .1 1.17c.36.3.9.25 1.21-.1l.21-.24.21.24c.17.19.41.29.66.29.2 0 .39-.06.55-.2.36-.3.41-.82.1-1.17l-.87-.99ZM22.17 41.96c-.16-.19-.4-.29-.65-.29s-.49.11-.65.29l-.87.99a.81.81 0 0 0 .1 1.17c.16.13.36.2.55.2.24 0 .49-.1.66-.29l.21-.24.21.24c.31.35.85.39 1.21.1.36-.3.41-.82.1-1.17l-.87-.99ZM34.33 41.96c-.16-.19-.4-.29-.65-.29s-.49.11-.65.29l-.87.99a.81.81 0 0 0 .1 1.17c.36.3.9.25 1.21-.1l.21-.24.21.24c.17.19.41.29.66.29.2 0 .39-.06.55-.2.36-.3.41-.82.1-1.17l-.87-.99ZM6.89 27.69a92.956 92.956 0 0 1 28.5 0 92.956 92.956 0 0 1-28.5 0ZM6.49 37.49a92.956 92.956 0 0 1 28.5 0 92.956 92.956 0 0 1-28.5 0Z" />
</svg>
<svg class="ball ball__1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 41.48 52.64" fill="#5386E4">
<path class="ball__path" d="M35.46 18.32A20.046 20.046 0 0 0 25 12.33v-2.01c.37-.23.7-.56.94-.98.07-.13.11-.27.11-.42V5.56c0-.45-.37-.82-.82-.82h-1.2V4c0-1.81-1.48-3.29-3.29-3.29S17.45 2.19 17.45 4v.74h-1.2c-.45 0-.82.37-.82.82v3.36c0 .15.04.29.11.42.25.42.57.75.94.98v2.01c-4 .86-7.65 2.94-10.46 5.99C2.6 22.02.71 26.85.71 31.9c0 11.04 8.99 20.03 20.03 20.03s20.03-8.99 20.03-20.03c0-5.05-1.89-9.88-5.31-13.59Z" style="fill:none;stroke:var(--color-ball-1);stroke-miterlimit:10;stroke-width:1.42px" />
<path class="ball__inner" d="M27.93 40.8h-.6v-.6c0-.45-.37-.82-.82-.82s-.82.37-.82.82v.6h-.6c-.45 0-.82.37-.82.82s.37.82.82.82h.6v.6c0 .45.37.82.82.82s.82-.37.82-.82v-.6h.6c.45 0 .82-.37.82-.82s-.37-.82-.82-.82ZM34.47 34.26h-.6v-.6c0-.45-.37-.82-.82-.82s-.82.37-.82.82v.6h-.6c-.45 0-.82.37-.82.82s.37.82.82.82h.6v.6c0 .45.37.82.82.82s.82-.37.82-.82v-.6h.6c.45 0 .82-.37.82-.82s-.37-.82-.82-.82ZM9.84 23.9h.6v.6c0 .45.37.82.82.82s.82-.37.82-.82v-.6h.6c.45 0 .82-.37.82-.82s-.37-.82-.82-.82h-.6v-.6c0-.45-.37-.82-.82-.82s-.82.37-.82.82v.6h-.6c-.45 0-.82.37-.82.82s.37.82.82.82ZM23.52 34.01l-4.44-.36-1.71-4.11c-.13-.3-.42-.5-.75-.5s-.63.2-.75.5l-1.71 4.11-4.44.36a.82.82 0 0 0-.71.56c-.1.31 0 .66.25.87l3.38 2.9-1.03 4.33c-.08.32.05.66.31.85.27.19.62.21.91.04l3.8-2.32 3.8 2.32c.13.08.28.12.43.12.17 0 .34-.05.48-.16a.8.8 0 0 0 .31-.85l-1.03-4.33 3.38-2.9c.25-.21.35-.56.25-.87a.806.806 0 0 0-.71-.56Zm-4.36 3.42c-.23.2-.33.51-.26.81l.69 2.91-2.55-1.56c-.13-.08-.28-.12-.43-.12s-.3.04-.43.12l-2.55 1.56.69-2.91c.07-.3-.03-.61-.26-.81l-2.27-1.94 2.98-.24c.31-.02.57-.22.69-.5l1.15-2.76 1.15 2.76c.12.28.38.48.69.5l2.98.24-2.27 1.94ZM30.09 26.76l2.15-1.84c.25-.21.35-.56.25-.87a.806.806 0 0 0-.71-.56l-2.82-.23-1.09-2.61c-.13-.3-.42-.5-.75-.5s-.63.2-.75.5l-1.09 2.61-2.82.23a.82.82 0 0 0-.71.56c-.1.31 0 .66.25.87l2.15 1.84-.66 2.75c-.08.32.05.66.31.85.27.19.62.21.91.04l2.41-1.48 2.41 1.48c.13.08.28.12.43.12.17 0 .34-.05.48-.16a.8.8 0 0 0 .31-.85l-.66-2.75Zm-1.44-.91c-.23.2-.33.51-.26.81l.32 1.33-1.16-.71a.813.813 0 0 0-.85 0l-1.16.71.32-1.33c.07-.3-.03-.61-.26-.81l-1.04-.89 1.36-.11c.31-.02.57-.22.69-.5l.52-1.26.52 1.26c.12.28.38.48.69.5l1.36.11-1.04.89Z" />
</svg>
<svg class="tree" xmlns="http://www.w3.org/2000/svg" width="204" height="363" viewBox="0 0 204.75 363.81">
<path d="M195.27 276.27c-5.4-7.5-11.6-14.3-18.5-20.1-1.8-1.5-3.6-3-4.7-5.1-1.1-2.1-1.1-5.1.5-6.7 1.1-1.1 2.7-1.3 4.1-1.9 7-2.7 9.7-12.5 7.4-20.1-2.2-7.6-8-13.3-13.9-18.1-4.1-3.4-8.4-6.7-10.9-11.5s-2.5-11.7 1.6-15.1c1.7-1.4 3.8-2.1 5.5-3.5 5.4-4.6 2.7-14.4-2.3-19.3-5.1-5-12-7.6-16.6-13.1s-5.3-16.1 1.1-18.9c1.3-.6 2.9-.8 4-1.8 2.6-2.6.3-7.2-2.1-10-6.8-8-13.5-16-20.3-24-1.2-1.4-2.5-3.3-2-5.2.9-3.1 5.3-2.2 7.7-4.1 3.2-2.5 1.4-7.9-.6-11.5-10.8-19.7-21.7-39.4-32.5-59.2-.1.3-.2.5-.4.8-.1-.3-.2-.5-.4-.8-10.8 19.7-21.7 39.4-32.5 59.2-2 3.6-3.7 9-.6 11.5 2.4 1.9 6.8 1.1 7.7 4.1.6 1.9-.7 3.7-2 5.2-6.8 8-13.5 16-20.3 24-2.4 2.8-4.8 7.4-2.1 10 1.1 1 2.6 1.2 4 1.8 6.4 2.8 5.7 13.4 1.1 18.9-4.6 5.5-11.5 8.1-16.6 13.1s-7.7 14.7-2.3 19.3c1.7 1.4 3.8 2.1 5.5 3.5 4 3.4 4.1 10.3 1.6 15.1s-6.8 8.1-10.9 11.5c-5.9 4.9-11.6 10.6-13.9 18.1-2.2 7.6.5 17.4 7.4 20.1 1.4.5 3 .8 4.1 1.9 1.7 1.6 1.6 4.6.5 6.7-1.1 2.1-3 3.6-4.7 5.1-6.9 5.9-13.1 12.6-18.5 20.1-3.8 5.4-7.4 11.8-6.5 18.5.8 5.7 4.8 10.4 9.5 13.1 4.7 2.7 10 3.8 15.3 4.6 19.69 3.11 39.69 3.79 59.51 2.08l-3.31 46.43h36.8l-3.31-46.43a245.53 245.53 0 0 0 59.51-2.08c5.3-.8 10.6-1.9 15.3-4.6 4.7-2.7 8.7-7.5 9.5-13.1.9-6.7-2.7-13.1-6.5-18.5Z" style="fill:none;stroke:var(--tree-color);stroke-miterlimit:10;stroke-width:5.67px" />
</svg>
</div>
<div class="star">
<div class="spark"></div>
</div>
<h1>Stylish Holidays</h1>
<p>Scroll me gently</p>
</div>
<div class="warning">Seems like your browser can't get the full experience, I suggest you use Chrome browser for now</div>
@import url("https://fonts.googleapis.com/css2?family=Birthstone&display=swap");
/* Base values for the offset-paths for the tree and balls */
@property --o-tree {
syntax: "<number>";
inherits: true;
initial-value: 1031.69;
}
@property --o-ball {
syntax: "<number>";
inherits: true;
initial-value: 148.443;
}
/* Star properties */
@property --star-offset {
syntax: "<percentage>";
inherits: true;
initial-value: 0%;
}
@property --star-opacity {
syntax: "<number>";
inherits: true;
initial-value: 1;
}
@property --star-transform {
syntax: "<transform-function>+ | none";
inherits: true;
initial-value: none;
}
/* Dash offsets of tree and balls, we will animate those */
@property --dash-offset-tree {
syntax: "<number>";
inherits: true;
initial-value: 0;
}
@property --dash-offset-ball-1 {
syntax: "<number>";
inherits: true;
initial-value: 0;
}
@property --dash-offset-ball-2 {
syntax: "<number>";
inherits: true;
initial-value: 0;
}
@property --dash-offset-ball-3 {
syntax: "<number>";
inherits: true;
initial-value: 0;
}
/* The inner opacity for the balls */
@property --ball-inner-opacity {
syntax: "<number>";
inherits: true;
initial-value: 0;
}
/* The hue / glow we are rotating and scroll-me intro opacity */
@property --h {
syntax: "<angle>";
inherits: true;
initial-value: 0deg;
}
@property --scroll-me-opacity {
syntax: "<number>";
inherits: true;
initial-value: 1;
}
:root {
--tree-color: #1d5b2d;
--color-ball-1: #5386e4;
--color-ball-2: #e072a4;
--color-ball-3: #0e7c7b;
scrollbar-color: var(--tree-color) #12313b;
}
.tree {
position: relative;
max-width: 100%;
height: auto;
filter: drop-shadow(0 0 3px oklch(97% 0.2 var(--h)));
stroke-dasharray: var(--o-tree);
stroke-dashoffset: var(--dash-offset-tree);
anchor-name: --tree;
}
.svg-items {
position: relative;
}
.ball {
position: absolute;
width: 42px;
height: auto;
filter: drop-shadow(0 0 1px hsl(var(--h) 70 80));
}
.ball__inner {
opacity: var(--ball-inner-opacity);
}
.ball__1 {
bottom: 78px;
left: 44px;
anchor-name: --ball-1;
.ball__path {
stroke-dasharray: var(--o-ball);
stroke-dashoffset: var(--dash-offset-ball-1);
}
}
.ball__2 {
bottom: 140px;
right: 57px;
anchor-name: --ball-2;
.ball__path {
stroke-dasharray: var(--o-ball);
stroke-dashoffset: var(--dash-offset-ball-2);
}
}
.ball__3 {
bottom: 220px;
left: 70px;
anchor-name: --ball-3;
.ball__path {
stroke-dasharray: var(--o-ball);
stroke-dashoffset: var(--dash-offset-ball-3);
}
}
.star {
--ball-path: path(
"M35.46 18.32A20.046 20.046 0 0 0 25 12.33v-2.01c.37-.23.7-.56.94-.98.07-.13.11-.27.11-.42V5.56c0-.45-.37-.82-.82-.82h-1.2V4c0-1.81-1.48-3.29-3.29-3.29S17.45 2.19 17.45 4v.74h-1.2c-.45 0-.82.37-.82.82v3.36c0 .15.04.29.11.42.25.42.57.75.94.98v2.01c-4 .86-7.65 2.94-10.46 5.99C2.6 22.02.71 26.85.71 31.9c0 11.04 8.99 20.03 20.03 20.03s20.03-8.99 20.03-20.03c0-5.05-1.89-9.88-5.31-13.59Z"
);
position: fixed;
top: anchor(var(--star-anchor) top);
left: anchor(var(--star-anchor) left);
opacity: var(--star-opacity);
offset-distance: var(--star-offset);
transform: var(--star-transform);
transform-origin: center;
offset-path: path(
"M195.27 276.27c-5.4-7.5-11.6-14.3-18.5-20.1-1.8-1.5-3.6-3-4.7-5.1-1.1-2.1-1.1-5.1.5-6.7 1.1-1.1 2.7-1.3 4.1-1.9 7-2.7 9.7-12.5 7.4-20.1-2.2-7.6-8-13.3-13.9-18.1-4.1-3.4-8.4-6.7-10.9-11.5s-2.5-11.7 1.6-15.1c1.7-1.4 3.8-2.1 5.5-3.5 5.4-4.6 2.7-14.4-2.3-19.3-5.1-5-12-7.6-16.6-13.1s-5.3-16.1 1.1-18.9c1.3-.6 2.9-.8 4-1.8 2.6-2.6.3-7.2-2.1-10-6.8-8-13.5-16-20.3-24-1.2-1.4-2.5-3.3-2-5.2.9-3.1 5.3-2.2 7.7-4.1 3.2-2.5 1.4-7.9-.6-11.5-10.8-19.7-21.7-39.4-32.5-59.2-.1.3-.2.5-.4.8-.1-.3-.2-.5-.4-.8-10.8 19.7-21.7 39.4-32.5 59.2-2 3.6-3.7 9-.6 11.5 2.4 1.9 6.8 1.1 7.7 4.1.6 1.9-.7 3.7-2 5.2-6.8 8-13.5 16-20.3 24-2.4 2.8-4.8 7.4-2.1 10 1.1 1 2.6 1.2 4 1.8 6.4 2.8 5.7 13.4 1.1 18.9-4.6 5.5-11.5 8.1-16.6 13.1s-7.7 14.7-2.3 19.3c1.7 1.4 3.8 2.1 5.5 3.5 4 3.4 4.1 10.3 1.6 15.1s-6.8 8.1-10.9 11.5c-5.9 4.9-11.6 10.6-13.9 18.1-2.2 7.6.5 17.4 7.4 20.1 1.4.5 3 .8 4.1 1.9 1.7 1.6 1.6 4.6.5 6.7-1.1 2.1-3 3.6-4.7 5.1-6.9 5.9-13.1 12.6-18.5 20.1-3.8 5.4-7.4 11.8-6.5 18.5.8 5.7 4.8 10.4 9.5 13.1 4.7 2.7 10 3.8 15.3 4.6 19.69 3.11 39.69 3.79 59.51 2.08l-3.31 46.43h36.8l-3.31-46.43a245.53 245.53 0 0 0 59.51-2.08c5.3-.8 10.6-1.9 15.3-4.6 4.7-2.7 8.7-7.5 9.5-13.1.9-6.7-2.7-13.1-6.5-18.5Z"
);
@container style(--star-anchor: --ball-1) {
offset-path: var(--ball-path);
}
@container style(--star-anchor: --ball-2) {
offset-path: var(--ball-path);
}
@container style(--star-anchor: --ball-3) {
offset-path: var(--ball-path);
}
}
@keyframes story {
10% {
--scroll-me-opacity: 0;
}
24% {
--star-opacity: 1;
}
25% {
--star-offset: 100%;
--star-anchor: --tree;
--star-opacity: 0;
--dash-offset-tree: 0;
}
25.1% {
--star-offset: 0%;
--star-anchor: --ball-1;
--dash-offset-ball-1: var(--o-ball);
}
28%,
49% {
--star-opacity: 1;
}
50% {
--star-offset: 100%;
--star-anchor: --ball-1;
--star-opacity: 0;
--dash-offset-ball-1: 0;
}
50.1% {
--star-offset: 0%;
--star-anchor: --ball-2;
--dash-offset-ball-2: var(--o-ball);
}
53%,
74% {
--star-opacity: 1;
}
75% {
--star-offset: 100%;
--star-anchor: --ball-2;
--star-opacity: 0;
--dash-offset-ball-2: 0;
}
75.1% {
--star-offset: 0%;
--star-anchor: --ball-3;
--dash-offset-ball-3: var(--o-ball);
}
78%,
96% {
--star-opacity: 1;
}
97% {
--star-offset: 100%;
--star-transform: translate(0, 0) scale(1);
--star-anchor: --ball-3;
--star-opacity: 0;
--dash-offset-ball-3: 0;
--ball-inner-opacity: 0;
}
97.1% {
--star-anchor: --tree;
--star-transform: translate(160px, 0) scale(1) rotate(-17deg);
}
100% {
--star-offset: 100%;
--star-anchor: --tree;
--star-transform: translate(280px, 88px) scale(4) rotate(-17deg);
--star-opacity: 1;
--dash-offset-tree: 0;
--dash-offset-ball-1: 0;
--dash-offset-ball-2: 0;
--dash-offset-ball-3: 0;
--ball-inner-opacity: 1;
--scroll-me-opacity: 0;
}
}
.tree-wrapper {
--star-anchor: --tree;
--dash-offset-tree: var(--o-tree);
--dash-offset-ball-1: var(--o-ball);
--dash-offset-ball-2: var(--o-ball);
--dash-offset-ball-3: var(--o-ball);
--scroll-me-opacity: 1;
position: fixed;
inset: 0;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
max-height: 100vh;
@supports (animation-timeline: --page-scroller) {
animation: story auto linear;
animation-timeline: --page-scroller;
}
@media (prefers-reduced-motion) {
animation: story 0s linear;
}
@supports not (animation-timeline: --page-scroller) {
--star-offset: 100%;
--star-opacity: 1;
--dash-offset-tree: 0;
--dash-offset-ball-1: 0;
--dash-offset-ball-2: 0;
--dash-offset-ball-3: 0;
--ball-inner-opacity: 1;
--scroll-me-opacity: 0;
}
@supports not (anchor-name: --page-scroller) {
--star-transform: translate(529px, 151px) scale(4) rotate(-17deg);
}
@media (height < 600px) {
scale: 0.7;
}
}
*,
*::before,
*::after {
box-sizing: border-box;
}
html {
scroll-timeline: --page-scroller block;
}
body {
background: radial-gradient(at top, #12313b, #000822);
font-family: "Birthstone", serif;
min-height: 100vh;
margin: 0;
animation: hueRotate 15s linear infinite;
@supports (animation-timeline: --page-scroller) {
min-height: 500vh;
}
}
.spark {
width: 16px;
height: 16px;
background: oklch(97% 0.1 var(--h));
border-radius: 50%;
box-shadow: 0 0 20px #00ff00, 0 0 40px #00ff00, 0 0 80px #00ff00;
z-index: -1;
clip-path: polygon(
50% 0%,
61% 35%,
98% 35%,
68% 57%,
79% 91%,
50% 70%,
21% 91%,
32% 57%,
2% 35%,
39% 35%
);
}
h1 {
font-size: clamp(2.1875rem, 0.6612rem + 7.6316vw, 4rem);
background: linear-gradient(90deg, oklch(90% 0.3 var(--h)), #fff);
opacity: var(--ball-inner-opacity);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
margin: 0;
}
p {
font-size: clamp(2.1875rem, 0.6612rem + 7.6316vw, 4rem);
background: linear-gradient(45deg, oklch(90% 0.3 var(--h)), #fff);
opacity: var(--scroll-me-opacity);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
margin: 0;
}
@keyframes hueRotate {
from {
--h: 0deg;
}
to {
--h: 360deg;
}
}
.warning {
position: fixed;
font-family: sans-serif;
background: lightyellow;
color: black;
top: 0;
left: 0;
width: 200px;
line-height: 1.5;
padding: 20px;
@supports (animation-timeline: --page-scroller) {
display: none;
}
@supports (anchor-name: --page-scroller) {
display: none;
}
}
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.