<div class="demo">
<main>
<section class="heart-start">
<div class="heart heart-outline">
</div>
</section>
<section>
<div class="heart heart-inside">
</div>
</section>
<section>
</section>
<section>
<span class="text">CSS</span>
</section>
</main>
<div class="scroll-info">
<span>Scroll</span>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true">
<path stroke-linecap="round" stroke-linejoin="round" d="M19.5 13.5L12 21m0 0l-7.5-7.5M12 21V3" />
</svg>
</div>
</div>
@import url('https://fonts.googleapis.com/css2?family=Mukta:wght@800&display=swap');
:root {
--heart-left: linear-gradient(to right, #f221c1, #fa0e2d, #e00a49);
--heart-right: linear-gradient(to left, #f221c1, #fa0e2d, #e00a49);
}
main {
block-size: 100vh;
scroll-snap-type: y mandatory;
overscroll-behavior-y: contain;
overflow-x: hidden;
overflow-y: auto;
scroll-timeline: --heartTimeline block;
scroll-padding-block: 100px;
}
section {
position: sticky;
top: 0;
display: flex;
min-block-size: 100vh;
scroll-snap-align: center;
align-items: center;
justify-content: center;
z-index: 2;
}
.heart {
position: relative;
width: 24px;
height: 24px;
transform: scale(10);
}
.heart::before,
.heart::after {
position: absolute;
inset-inline: 0;
inset-block: 0;
content: "";
content: "";
}
.heart::before {
background: var(--heart-left);
transform-origin: right bottom;
}
.heart::after {
background: var(--heart-right);
transform-origin: left bottom;
}
.heart-outline {
clip-path: path(
"M12 21.593c-5.63-5.539-11-10.297-11-14.402 0-3.791 3.068-5.191 5.281-5.191 1.312 0 4.151.501 5.719 4.457 1.59-3.968 4.464-4.447 5.726-4.447 2.54 0 5.274 1.621 5.274 5.181 0 4.069-5.136 8.625-11 14.402m5.726-20.583c-2.203 0-4.446 1.042-5.726 3.238-1.285-2.206-3.522-3.248-5.719-3.248-3.183 0-6.281 2.187-6.281 6.191 0 4.661 5.571 9.429 12 15.809 6.43-6.38 12-11.148 12-15.809 0-4.011-3.095-6.181-6.274-6.181"
);
animation-duration: 3s;
animation-direction: alternate;
animation-name: zoomHeart;
animation-timeline: --heartTimeline ;
}
.heart-outline::before,
.heart-outline::after {
animation-duration: 3s;
animation-direction: alternate;
animation-timeline: --heartTimeline ;
}
.heart-outline::before {
transform: translateX(-40%) rotate(-90deg);
animation-name: gradientInLeft;
}
.heart-outline::after {
transform: translateX(40%) rotate(90deg);
animation-name: gradientInRight;
}
.heart-inside {
position: relative;
width: 24px;
height: 24px;
clip-path: path(
"M12 4.248c-3.148-5.402-12-3.825-12 2.944 0 4.661 5.571 9.427 12 15.808 6.43-6.381 12-11.147 12-15.808 0-6.792-8.875-8.306-12-2.944z"
);
transform: scale(10);
opacity: 0;
animation-duration: 3s;
animation-direction: alternate;
animation-name: fillHeart;
animation-timeline: --heartTimeline ;
}
.heart-inside::before {
transform: translateX(-50%) rotate(0);
}
.heart-inside::after {
transform: translateX(50%) rotate(0);
}
.text {
font-size: 3.5rem;
animation-duration: 3s;
animation-direction: alternate;
animation-name: zoomText;
animation-timeline: --heartTimeline ;
}
.scroll-info {
display: flex;
justify-content: center;
align-items: center;
gap: 12px;
position: fixed;
bottom: 20px;
left: 50%;
z-index: 10;
transform: translateX(-50%);
font-size: 2.3rem;
color: #fff;
animation-direction: alternate;
animation-name: fadeOut;
animation-timeline: --heartTimeline ;
background: black;
}
.scroll-info svg {
display: block;
width: 26px;
height: 26px;
animation: bounce 2s infinite;
color: #fff;
}
@keyframes gradientInLeft {
from {
transform: translateX(-40%) rotate(-90deg);
}
33%,
100% {
transform: translateX(-50%) rotate(0);
}
}
@keyframes gradientInRight {
from {
transform: translateX(40%) rotate(90deg);
}
33%,
100% {
transform: translateX(50%) rotate(0);
}
}
@keyframes fillHeart {
from,
33% {
opacity: 0;
transform: scale(6);
}
66%,
100% {
opacity: 1;
transform: scale(10);
}
}
@keyframes zoomHeart {
from,
33% {
transform: scale(14);
}
66%,
100% {
transform: scale(10);
}
}
@keyframes zoomText {
from,
66% {
opacity: 0;
color: black;
}
96% {
color: black;
}
100% {
opacity: 1;
color: white;
}
}
@keyframes fadeOut {
from {
bottom: 50%;
opacity: 1;
}
33% {
bottom: 20px;
opacity: 1;
}
80% {
opacity: 1;
}
100% {
opacity: 0;
bottom: 20px;
}
}
@keyframes bounce {
0%,
20%,
50%,
80%,
100% {
transform: translateY(0);
}
40% {
transform: translateY(-30px);
}
60% {
transform: translateY(-15px);
}
}
*,
*::before,
*::after {
box-sizing: border-box;
}
body {
margin: 0;
padding: 0;
font-family: "Mukta", sans-serif;
font-weight: 800;
color: black;
background: black;
}
@supports not (animation-timeline: view()) {
section, .scroll-info {
display: none;
}
}