¸¶¿ì½º¸¦ ½ºÅ©·ÑÇϸé Ä«µå°¡ ½×ÀÌ´Â ¾Ö´Ï¸ÞÀÌ¼Ç È¿°úÀÔ´Ï´Ù.
HTML ¼Ò½º
<div class="space space--small"></div>
<div class="cards">
<div class="card" data-index="0">
<div class="card__inner">
<div class="card__image-container">
<img
class="card__image"
src="https://images.unsplash.com/photo-1620207418302-439b387441b0?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1200&q=100"
alt=""
/>
</div>
<div class="card__content">
<h1 class="card__title">Card Title</h1>
<p class="card__description">
Lorem ipsum dolor sit amet consectetur adipisicing elit. Ab dicta
error nam eaque. Eum fuga laborum quos expedita iste saepe
similique, unde possimus quia at magnam sed cupiditate?
Reprehenderit, harum!
</p>
</div>
</div>
</div>
<div class="card" data-index="0">
<div class="card__inner">
<div class="card__image-container">
<img
class="card__image"
src="https://images.unsplash.com/photo-1620207418302-439b387441b0?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1200&q=100"
alt=""
/>
</div>
<div class="card__content">
<h1 class="card__title">Card Title</h1>
<p class="card__description">
Lorem ipsum dolor sit amet consectetur adipisicing elit. Ab dicta
error nam eaque. Eum fuga laborum quos expedita iste saepe
similique, unde possimus quia at magnam sed cupiditate?
Reprehenderit, harum!
</p>
</div>
</div>
</div>
<div class="card" data-index="0">
<div class="card__inner">
<div class="card__image-container">
<img
class="card__image"
src="https://images.unsplash.com/photo-1620207418302-439b387441b0?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1200&q=100"
alt=""
/>
</div>
<div class="card__content">
<h1 class="card__title">Card Title</h1>
<p class="card__description">
Lorem ipsum dolor sit amet consectetur adipisicing elit. Ab dicta
error nam eaque. Eum fuga laborum quos expedita iste saepe
similique, unde possimus quia at magnam sed cupiditate?
Reprehenderit, harum!
</p>
</div>
</div>
</div>
</div>
<div class="space"></div>
CSS ¼Ò½º
* {
box-sizing: border-box;
}
body {
background: hsl(265.3, 10%, 75%);
font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI',
Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue',
sans-serif;
}
.card {
position: sticky;
top: 0;
}
.card__inner {
will-change: transform;
background: white;
border-radius: 14px;
display: flex;
overflow: hidden;
box-shadow: 0 25px 50px -12px hsla(265.3, 20%, 10%, 35%);
transform-origin: center top;
}
.cards {
width: 100%;
max-width: 900px;
margin: 0 auto;
display: grid;
grid-template-rows: repeat(var(--cards-count), var(--card-height));
gap: 40px 0;
}
.card__image-container {
display: flex;
width: 40%;
flex-shrink: 0;
}
.card__image {
width: 100%;
height: 100%;
object-fit: cover;
aspect-ratio: 1;
}
.card__content {
padding: 40px 30px;
display: flex;
flex-direction: column;
}
.card__title {
padding: 0;
margin: 0;
font-size: 60px;
font-weight: 600;
color: #16263a;
}
.card__description {
line-height: 1.4;
font-size: 24px;
color: #16263a;
}
.space {
height: 90vh;
}
.space--small {
height: 40vh;
}
@media (max-width: 600px) {
.card__inner {
flex-direction: column;
}
.card__image-container {
width: 100%;
}
.card__image {
aspect-ratio: 16 / 9;
}
.card__title {
font-size: 32px;
}
.card__description {
font-size: 16px;
}
.card__content {
padding: 30px 20px;
}
}
JS ¼Ò½º
const { ScrollObserver, valueAtPercentage } = aat
const cardsContainer = document.querySelector('.cards')
const cards = document.querySelectorAll('.card')
cardsContainer.style.setProperty('--cards-count', cards.length)
cardsContainer.style.setProperty(
'--card-height',
`${cards[0].clientHeight}px`
)
Array.from(cards).forEach((card, index) => {
const offsetTop = 20 + index * 20
card.style.paddingTop = `${offsetTop}px`
if (index === cards.length - 1) {
return
}
const toScale = 1 - (cards.length - 1 - index) * 0.1
const nextCard = cards[index + 1]
const cardInner = card.querySelector('.card__inner')
ScrollObserver.Element(nextCard, {
offsetTop,
offsetBottom: window.innerHeight - card.clientHeight
}).onScroll(({ percentageY }) => {
cardInner.style.scale = valueAtPercentage({
from: 1,
to: toScale,
percentage: percentageY
})
cardInner.style.filter = `brightness(${valueAtPercentage({
from: 1,
to: 0.6,
percentage: percentageY
})})`
})
})
÷ºÎµÈ ÆÄÀÏ ¶Ç´Â ÇØ´ç »çÀÌÆ®¿¡¼ ¼Ò½ºÈ®ÀÎÀÌ °¡´ÉÇÕ´Ï´Ù