效果图:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
body {
background-color: var(--color-neutral-900);
color: var(--color-light);
font-size: var(--size-font);
margin: 0;
padding: 0;
}
.cloneable {
padding: var(--container-padding);
justify-content: center;
align-items: center;
min-height: 100vh;
display: flex;
position: relative;
}
.parallax__fade {
--color-dark-rgb: 0, 0, 0;
background: linear-gradient(to top, rgba(var(--color-dark-rgb), 1) 0%, rgba(var(--color-dark-rgb), 0.738) 19%, rgba(var(--color-dark-rgb), 0.541) 34%, rgba(var(--color-dark-rgb), 0.382) 47%, rgba(var(--color-dark-rgb), 0.278) 56.5%, rgba(var(--color-dark-rgb), 0.194) 65%, rgba(var(--color-dark-rgb), 0.126) 73%, rgba(var(--color-dark-rgb), 0.075) 80.2%, rgba(var(--color-dark-rgb), 0.042) 86.1%, rgba(var(--color-dark-rgb), 0.021) 91%, rgba(var(--color-dark-rgb), 0.008) 95.2%, rgba(var(--color-dark-rgb), 0.002) 98.2%, transparent 100%);
}
.osmo-icon-svg {
width: 8em;
position: relative;
}
.parallax__header {
z-index: 2;
padding: var(--section-padding) var(--container-padding);
justify-content: center;
align-items: center;
min-height: 100svh;
display: flex;
position: relative;
}
.parallax {
width: 100%;
position: relative;
overflow: hidden;
}
.parallax__content {
background-color: black;
padding: var(--section-padding) var(--container-padding);
justify-content: center;
align-items: center;
min-height: 100svh;
display: flex;
position: relative;
}
.cover {
object-fit: cover;
width: 100%;
max-width: none;
height: 100%;
position: absolute;
top: 0;
left: 0;
}
.parallax__visuals {
object-fit: cover;
width: 100%;
max-width: none;
height: 120%;
position: absolute;
top: 0;
left: 0;
}
.parallax__placeholder {
z-index: 0;
opacity: 0;
object-fit: cover;
width: 100%;
max-width: none;
height: 100%;
position: absolute;
top: 0;
left: 0;
}
.parallax__layers {
object-fit: cover;
width: 100%;
max-width: none;
height: 100%;
position: absolute;
top: 0;
left: 0;
overflow: hidden;
}
.cover-copy {
object-fit: cover;
width: 100%;
max-width: none;
height: 100%;
position: absolute;
top: 0;
left: 0;
}
.parallax__fade {
z-index: 30;
object-fit: cover;
width: 100%;
max-width: none;
height: 20%;
position: absolute;
bottom: 0;
left: 0;
}
.parallax__black-line-overflow {
z-index: 20;
background-color: var(--color-black);
width: 100%;
height: 2px;
position: absolute;
bottom: -1px;
left: 0;
}
.parallax__title {
pointer-events: auto;
text-align: center;
text-transform: none;
margin-top: 0;
margin-bottom: .1em;
margin-right: .075em;
font-family: PP Neue Corp Wide, sans-serif;
font-size: 11vw;
font-weight: 800;
line-height: 1;
position: relative;
}
.parallax__radial-gradient {
z-index: 10;
background-image: radial-gradient(circle farthest-corner at 50% 50%, transparent, var(--color-black));
opacity: .5;
pointer-events: none;
mix-blend-mode: multiply;
position: fixed;
inset: 0;
}
.parallax__layer-title {
justify-content: center;
align-items: center;
width: 100%;
height: 100svh;
display: flex;
position: absolute;
top: 0;
left: 0;
}
.parallax__layer-img {
pointer-events: none;
object-fit: cover;
width: 100%;
max-width: none;
height: 117.5%;
position: absolute;
top: -17.5%;
left: 0;
}
.parallax__layer-img.is-third {
top: -20%;
}
@font-face {
font-family: 'PP Neue Corp Wide';
src: url('https://cdn.prod.website-files.com/671752cd4027f01b1b8f1c7f/6717e399d30a606fed425914_PPNeueCorp-WideUltrabold.woff2') format('woff2');
font-weight: 800;
font-style: normal;
font-display: swap;
}
</style>
</head>
<body>
<div class="parallax">
<section class="parallax__header">
<div class="parallax__visuals">
<div class="parallax__black-line-overflow"></div>
<div data-parallax-layers class="parallax__layers">
<img src="https://cdn.prod.website-files.com/671752cd4027f01b1b8f1c7f/6717795be09b462b2e8ebf71_osmo-parallax-layer-3.webp" loading="eager" width="800" data-parallax-layer="1" alt="" class="parallax__layer-img">
<img src="https://cdn.prod.website-files.com/671752cd4027f01b1b8f1c7f/6717795b4d5ac529e7d3a562_osmo-parallax-layer-2.webp" loading="eager" width="800" data-parallax-layer="2" alt="" class="parallax__layer-img">
<div data-parallax-layer="3" class="parallax__layer-title">
<h2 class="parallax__title">Parallax</h2>
</div>
<img src="https://cdn.prod.website-files.com/671752cd4027f01b1b8f1c7f/6717795bb5aceca85011ad83_osmo-parallax-layer-1.webp" loading="eager" width="800" data-parallax-layer="4" alt="" class="parallax__layer-img">
</div>
<div class="parallax__fade"></div>
</div>
</section>
<section class="parallax__content">
<svg xmlns="http://www.w3.org/2000/svg" width="100%" viewbox="0 0 160 160" fill="none" class="osmo-icon-svg"><path d="M94.8284 53.8578C92.3086 56.3776 88 54.593 88 51.0294V0H72V59.9999C72 66.6273 66.6274 71.9999 60 71.9999H0V87.9999H51.0294C54.5931 87.9999 56.3777 92.3085 53.8579 94.8283L18.3431 130.343L29.6569 141.657L65.1717 106.142C67.684 103.63 71.9745 105.396 72 108.939V160L88.0001 160L88 99.9999C88 93.3725 93.3726 87.9999 100 87.9999H160V71.9999H108.939C105.407 71.9745 103.64 67.7091 106.12 65.1938L106.142 65.1716L141.657 29.6568L130.343 18.3432L94.8284 53.8578Z" fill="#FFFFFF"></path></svg>
</section>
</div>
<script src="https://cdn.jsdelivr.net/npm/gsap@3.12.5/dist/gsap.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/gsap@3.12.5/dist/ScrollTrigger.min.js"></script>
<script src="https://unpkg.com/lenis@1.1.14/dist/lenis.min.js"></script>
</body>
<script>
document.addEventListener("DOMContentLoaded", () => {
gsap.registerPlugin(ScrollTrigger);
document.querySelectorAll('[data-parallax-layers]').forEach((triggerElement) => {
let tl = gsap.timeline({
scrollTrigger: {
trigger: triggerElement,
start: "0% 0%",
end: "100% 0%",
scrub: 0
}
});
const layers = [
{ layer: "1", yPercent: 70 },
{ layer: "2", yPercent: 55 },
{ layer: "3", yPercent: 40 },
{ layer: "4", yPercent: 10 }
];
layers.forEach((layerObj, idx) => {
tl.to(
triggerElement.querySelectorAll(`[data-parallax-layer="${layerObj.layer}"]`),
{
yPercent: layerObj.yPercent,
ease: "none"
},
idx === 0 ? undefined : "<"
);
});
});
});
const lenis = new Lenis();
lenis.on('scroll', ScrollTrigger.update);
gsap.ticker.add((time) => { lenis.raf(time * 1000); });
gsap.ticker.lagSmoothing(0);
</script>
</html>