QUOTE THE DAY
“ 당신이 6개월 이상 한 번도 보지 않은 코드는 다른 사람이 다시 만드는 게 훨씬 더 나을 수 있다. ”
-
이글슨 (Eagleson)
반응형
패럴랙스 이펙트란?
패럴랙스 이펙트는 사용자가 스크롤을 내리거나 올릴 때, 배경과 함께 웹 페이지의 요소들이 서로 다른 속도로 움직이는 것을 말합니다. 이는 일반적으로 CSS와 JavaScript를 사용하여 구현되며, 웹 페이지를 더욱 동적이고 인터랙티브하게 만들어줍니다.
웹사이트 패럴랙스 이펙트를 사용하면 사용자가 웹 페이지를 스크롤 할 때, 배경 이미지와 함께 다양한 요소들이 움직이는 것처럼 보입니다. 예를 들어, 웹 페이지에 일러스트나 이미지를 배경으로 사용하면 이를 이용하여 사용자의 눈길을 이끌거나 페이지의 구조를 강조할 수 있습니다. 또는 텍스트나 버튼과 같은 요소들도 패럴랙스 이펙트를 이용하여 동적인 효과를 줄 수 있습니다.
패럴랙스 이펙트는 웹 디자인의 트렌드 중 하나로, 사용자 경험을 개선하고 웹 페이지를 더욱 흥미롭고 동적으로 만들어줍니다. 하지만, 지나친 사용은 사용자 경험을 해치고 성능 저하를 일으킬 수 있으므로 적절한 사용이 필요합니다.
패럴랙스 이펙트 사이트 코드
<main id="main">
<div class="parallax__wrap">
<section id="section1" class="parallax__item">
<span class="parallax__item__num">01</span>
<h2 class="parallax__item__title">Section1</h2>
<figure class="parallax__item__imgWrap reveal">
<div class="parallax__item__img"></div>
</figure>
<p class="parallax__item__desc reveal" data-delay="1500">행동이 모든 것을 결정한다. 운명은 행동에서 비롯된다.</p>
</section>
<!-- //section1 -->
<section id="section2" class="parallax__item">
<span class="parallax__item__num">02</span>
<h2 class="parallax__item__title">Section2</h2>
<figure class="parallax__item__imgWrap reveal">
<div class="parallax__item__img"></div>
</figure>
<p class="parallax__item__desc reveal" data-delay="1500">작은 성공이 큰 성공으로 이어진다.</p>
</section>
<!-- //section2 -->
<section id="section3" class="parallax__item">
<span class="parallax__item__num">03</span>
<h2 class="parallax__item__title">Section3</h2>
<figure class="parallax__item__imgWrap reveal reveal-RTL">
<div class="parallax__item__img"></div>
</figure>
<p class="parallax__item__desc reveal reveal-RTL" data-delay="1500">인생은 결코 공평하지 않다. 그러나 그것을 이길 수 있다.</p>
</section>
<!-- //section3 -->
<section id="section4" class="parallax__item">
<span class="parallax__item__num">04</span>
<h2 class="parallax__item__title">Section4</h2>
<figure class="parallax__item__imgWrap reveal reveal-TTB">
<div class="parallax__item__img"></div>
</figure>
<p class="parallax__item__desc reveal reveal-TTB" data-delay="1500">성취하지 못한 것은 아직 해보지 않은 것뿐입니다.</p>
</section>
<!-- //section4 -->
<section id="section5" class="parallax__item">
<span class="parallax__item__num">05</span>
<h2 class="parallax__item__title">Section5</h2>
<figure class="parallax__item__imgWrap reveal reveal-BTT">
<div class="parallax__item__img"></div>
</figure>
<p class="parallax__item__desc reveal reveal-BTT" data-delay="1500">가장 높은 산은 한 발짝부터 시작된다.</p>
</section>
<!-- //section5 -->
<section id="section6" class="parallax__item">
<span class="parallax__item__num">06</span>
<h2 class="parallax__item__title">Section6</h2>
<figure class="parallax__item__imgWrap reveal reveal-TWO">
<div class="parallax__item__img"></div>
</figure>
<p class="parallax__item__desc reveal reveal-TWO" data-delay="1500">목표를 향한 첫 걸음은 용기이다.</p>
</section>
<!-- //section6 -->
<section id="section7" class="parallax__item">
<span class="parallax__item__num">07</span>
<h2 class="parallax__item__title">Section7</h2>
<figure class="parallax__item__imgWrap reveal reveal-TWO reveal-RTL">
<div class="parallax__item__img"></div>
</figure>
<p class="parallax__item__desc reveal reveal-TWO reveal-RTL" data-delay="1500">우리의 인생은 우리의 생각과 믿음이 결정한다.</p>
</section>
<!-- //section7 -->
<section id="section8" class="parallax__item">
<span class="parallax__item__num">08</span>
<h2 class="parallax__item__title">Section8</h2>
<figure class="parallax__item__imgWrap reveal reveal-TWO reveal-TTB">
<div class="parallax__item__img"></div>
</figure>
<p class="parallax__item__desc reveal reveal-TWO reveal-TTB" data-delay="1500">언제나 새로운 것을 배울 수 있고, 새로운 것을 경험할 수 있다.</p>
</section>
<!-- //section8 -->
<section id="section9" class="parallax__item">
<span class="parallax__item__num">09</span>
<h2 class="parallax__item__title">Section9</h2>
<figure class="parallax__item__imgWrap reveal reveal-TWO reveal-BTT">
<div class="parallax__item__img"></div>
</figure>
<p class="parallax__item__desc reveal reveal-TWO reveal-BTT" data-delay="1500">한계는 우리가 만든 것이며, 우리가 이겨낼 수 있다.</p>
</section>
<!-- //section9 -->
</div>
</main>
<!-- //main -->
- section 요소의 id 속성은 "section1"로 설정되어 있습니다. id 속성은 요소를 식별하기 위해 사용될 수 있는 고유한 식별자입니다.
- class 속성에 "parallax__item" 클래스가 설정되어 있습니다. 클래스는 여러 요소를 그룹화하거나 스타일을 적용하기 위해 사용됩니다.
- <span> 요소에 "parallax__item__num" 클래스가 설정되어 있습니다. 이 요소는 섹션의 번호를 나타내기 위해 사용될 수 있습니다.
- <h2> 요소에 "parallax__item__title" 클래스가 설정되어 있습니다. 이 요소는 섹션의 제목을 나타내기 위해 사용될 수 있습니다.
- <figure> 요소에 "parallax__item__imgWrap" 클래스와 "reveal" 클래스가 설정되어 있습니다. 이 요소는 이미지를 감싸는 컨테이너 역할을 하며, "reveal" 클래스는 스크롤 시 이미지를 표시하기 위한 동적인 효과를 구현하는 데 사용될 수 있습니다.
- <div> 요소에 "parallax__item__img" 클래스가 설정되어 있습니다. 이 요소는 실제 이미지를 나타낼 수 있는 공간을 제공할 수 있습니다.
- <p> 요소에 "parallax__item__desc" 클래스와 "reveal" 클래스가 설정되어 있습니다. 이 요소는 섹션의 설명을 담고 있으며, "reveal" 클래스는 스크롤 시에 텍스트를 동적으로 표시하는 효과를 구현하는 데 사용될 수 있습니다. 또한, data-delay 속성은 1500밀리초(1.5초)의 지연 시간을 나타내며, 텍스트가 표시되기 전에 대기해야 하는 시간을 설정할 수 있습니다.
위의 코드는 한 섹션을 구성하는 요소들을 나타내며, 각 요소에는 특정 클래스와 데이터 속성이 설정되어 있습니다. 이를 통해 스타일링이나 동적인 효과를 적용할 수 있습니다.
CSS
.reveal > div,
.reveal > span {
opacity: 0;
}
.reveal.show > div,
.reveal.show > span {
animation: opacity 1s linear forwards;
}
.reveal {
position: relative;
}
/* 1개 */
.reveal::before {
content: '';
position: absolute;
left: 0;
top: 0;
width: 0%;
height: 100%;
background-color: #fff;
z-index: 1;
}
.reveal.show::before {
animation: reveal 1s cubic-bezier(0.075, 0.82, 0.165, 1);
}
.reveal.reveal-RTL.show::before {
animation: reveal-RTL 1s cubic-bezier(0.075, 0.82, 0.165, 1);
}
.reveal.reveal-TTB.show::before {
animation: reveal-TTB 1s cubic-bezier(0.075, 0.82, 0.165, 1);
}
.reveal.reveal-BTT.show::before {
animation: reveal-BTT 1s cubic-bezier(0.075, 0.82, 0.165, 1);
}
- .reveal > div, .reveal > span 선택자는 "reveal" 클래스의 자식인 <div> 요소와 <span> 요소를 선택합니다.
- 선택된 요소들의 opacity 속성을 0으로 설정하여 초기에 투명하게 만듭니다.
- .reveal.show > div, .reveal.show > span 선택자는 "reveal" 클래스가 있고 "show" 클래스가 추가된 자식 <div> 요소와 <span> 요소를 선택합니다.
- 선택된 요소들에 animation 속성을 적용하여 opacity 애니메이션을 1초 동안 선형적으로 적용합니다.
- .reveal 클래스에는 position 속성을 relative로 설정합니다.
- .reveal::before 선택자는 "reveal" 클래스의 가상 요소인 ::before를 선택합니다.
- ::before 가상 요소에는 흰색 배경과 0%의 너비를 가진 절반 높이의 사각형을 생성합니다. 이 사각형은 요소의 왼쪽에 상대적으로 위치합니다.
- reveal.show::before 선택자는 "reveal" 클래스가 있고 "show" 클래스가 추가된 ::before 가상 요소를 선택합니다.
- 선택된 가상 요소에 animation 속성을 적용하여 reveal 애니메이션을 1초 동안 적용합니다. 이 애니메이션은 cubic-bezier 타이밍 함수를 사용합니다.
- .reveal.reveal-RTL.show::before, .reveal.reveal-TTB.show::before, .reveal.reveal-BTT.show::before 선택자들은 특정한 방향(RTL, TTB, BTT)을 가진 "reveal" 클래스에 "show" 클래스가 추가된 ::before 가상 요소를 선택합니다.
- 각각의 선택자에 해당하는 가상 요소에는 각각에 맞는 방향 애니메이션을 적용합니다.
/* 2개 */
.reveal.reveal-TWO::after {
content: '';
position: absolute;
left: 0;
top: 0;
width: 0;
height: 100%;
z-index: 1;
background-color: #45507ca4;
}
.reveal.show::after {
animation: reveal 1s 0.3s cubic-bezier(0.075, 0.82, 0.165, 1);
}
.reveal.reveal-RTL.show::after {
animation: reveal-RTL 1s 0.3s cubic-bezier(0.075, 0.82, 0.165, 1);
}
.reveal.reveal-TTB.show::after {
animation: reveal-TTB 1s 0.3s cubic-bezier(0.075, 0.82, 0.165, 1);
}
.reveal.reveal-BTT.show::after {
animation: reveal-BTT 1s 0.3s cubic-bezier(0.075, 0.82, 0.165, 1);
}
- .reveal.reveal-TWO::after 선택자는 "reveal" 클래스와 "reveal-TWO" 클래스를 가진 요소의 가상 요소인 ::after를 선택합니다.
- ::after 가상 요소는 절반 높이의 사각형으로, 요소의 왼쪽에 상대적으로 위치하며 투명한 상태입니다.
- .reveal.show::after 선택자는 "reveal" 클래스와 "show" 클래스가 추가된 ::after 가상 요소를 선택합니다.
- 선택된 가상 요소에 animation 속성을 적용하여 reveal 애니메이션을 1초 동안 적용합니다. 이 애니메이션은 0.3초의 지연 시간을 가지며, cubic-bezier 타이밍 함수를 사용합니다.
- .reveal.reveal-RTL.show::after, .reveal.reveal-TTB.show::after, .reveal.reveal-BTT.show::after 선택자들은 특정한 방향(RTL, TTB, BTT)을 가진 "reveal" 클래스에 "show" 클래스가 추가된 ::after 가상 요소를 선택합니다.
- 각각의 선택자에 해당하는 가상 요소에는 각각에 맞는 방향 애니메이션을 적용합니다.
/* animation */
@keyframes opacity {
0% {opacity: 0;}
60% {opacity: 0;}
70% {opacity: 1;}
100% {opacity: 1;}
}
@keyframes reveal {
0% {width: 0; left: 0;}
50% {width: 100%; left: 0;}
80% {width: 100%; left: 0;}
100% {width: 0; left: 100%;}
}
@keyframes reveal-RTL {
0% {width: 0; left: auto; right: 0;}
50% {width: 100%; left: auto; right: 0;}
80% {width: 100%; left: auto; right: 0;}
100% {width: 0; left: auto; right: 100%;}
}
@keyframes reveal-TTB {
0% {width: 100%; height: 0; top: 0;}
50% {width: 100%; height: 100%; top: 0;}
80% {width: 100%; height: 100%; top: 0;}
100% {width: 100%; height: 0; top: 100%;}
}
@keyframes reveal-BTT {
0% {width: 100%; height: 0; bottom: 0; top: auto;}
50% {width: 100%; height: 100%; bottom: 0; top: auto;}
80% {width: 100%; height: 100%; bottom: 0; top: auto;}
100% {width: 100%; height: 0; bottom: 100%; top: auto;}
}
- opacity 애니메이션:
- 0%부터 60%까지: 투명도를 0으로 설정하여 요소를 투명하게 만듭니다.
- 70%부터 100%까지: 투명도를 1로 설정하여 요소를 완전히 나타내게 합니다.
- reveal 애니메이션:
- 0%부터 50%까지: 요소의 너비를 0으로 설정하여 요소를 시작점에서 시작하게 합니다.
- 80%까지: 요소의 너비를 100%로 설정하여 요소를 가로 방향으로 전체적으로 펼치게 합니다.
- 100%까지: 요소의 너비를 다시 0으로 설정하여 요소를 끝점에서 사라지게 합니다. 이때 요소는 오른쪽 끝으로 이동합니다.
- reveal-RTL 애니메이션:
- 0%부터 50%까지: 요소의 너비를 0으로 설정하여 요소를 시작점에서 시작하게 합니다.
- 80%까지: 요소의 너비를 100%로 설정하여 요소를 가로 방향으로 전체적으로 펼치게 합니다.
- 100%까지: 요소의 너비를 다시 0으로 설정하여 요소를 끝점에서 사라지게 합니다. 이때 요소는 오른쪽 끝으로 이동합니다. (RTL은 Right-to-Left의 약자로 오른쪽에서 왼쪽으로 이동하는 효과를 의미합니다.)
- reveal-TTB 애니메이션:
- 0%부터 50%까지: 요소의 높이를 0으로 설정하여 요소를 시작점에서 시작하게 합니다.
- 80%까지: 요소의 높이를 100%로 설정하여 요소를 세로 방향으로 전체적으로 펼치게 합니다.
- 100%까지: 요소의 높이를 다시 0으로 설정하여 요소를 끝점에서 사라지게 합니다. 이때 요소는 아래쪽에서 위쪽으로 이동합니다. (TTB는 Top-to-Bottom의 약자로 위에서 아래로 이동하는 효과를 의미합니다.)
- reveal-BTT 애니메이션:
- 0%부터 50%까지: 요소의 높이를 0으로 설정하여 요소를 시작점에서 시작하게 합니다.
- 80%까지: 요소의 높이를 100%로 설정하여 요소를 세로 방향으로 전체적으로 펼치게 합니다.
- 100%까지: 요소의 높이를 다시 0으로 설정하여 요소를 끝점에서 사라지게 합니다. 이때 요소는 위쪽에서 아래쪽으로 이동합니다. (BTT는 Bottom-to-Top의 약자로 아래에서 위로 이동하는 효과를 의미합니다.)
JS
//만약에 reveal 클래스를 추가하면 자식요소에 span으로 감싸주기!
document.querySelectorAll("p.reveal").forEach(text => {
text.innerHTML = `<span>${text.innerHTML}</span>`
});
- document.querySelectorAll("p.reveal")는 HTML 문서에서 "reveal" 클래스를 가진 모든 <p> 요소를 선택합니다.
- forEach 메서드는 선택된 각 요소에 대해 반복 작업을 수행합니다.
- 반복 작업에서 text.innerHTML을 사용하여 각 요소의 내용을 가져옵니다.
- 템플릿 리터럴을 사용하여 새로운 내용을 생성합니다. <span> 요소는 기존 내용을 감싸기 위해 사용됩니다.
- text.innerHTML에 새로운 내용을 할당하여 기존 내용을 감싼 <span> 요소로 대체합니다.
function scroll(){
let scrollTop = window.scrollY || window.pageYOffset;
const reveals = document.querySelectorAll(".reveal");
reveals.forEach(reveal => {
let revealOffset = reveal.offsetTop + reveal.parentElement.offsetTop;
let revealDelay = reveal.dataset.delay;
// if(scrollTop >= revealOffset - window.innerHeight/2){
// reveal.classList.add("show");
// }
if(scrollTop >= revealOffset - window.innerHeight){
if(revealDelay == undefined){
reveal.classList.add("show");
} else {
setTimeout(() => {
reveal.classList.add("show");
}, revealDelay)
}
}
});
//info
document.querySelector(".scroll span").innerText = Math.round(scrollTop);
requestAnimationFrame(scroll);
}
scroll();
- scroll 함수는 스크롤 이벤트가 발생할 때 호출되는 함수입니다. 스크롤 위치를 가져오고, 요소를 선택합니다.
- scrollTop 변수는 window.scrollY 또는 window.pageYOffset을 통해 현재 스크롤 위치를 가져옵니다.
- reveals 변수는 클래스가 "reveal"인 모든 요소를 선택합니다.
- reveals.forEach 메서드를 사용하여 선택된 각 요소에 대해 반복 작업을 수행합니다.
- revealOffset 변수는 각 요소의 상위 요소에서의 오프셋과 offsetTop을 사용하여 현재 요소의 절대적인 위치를 계산합니다.
- revealDelay 변수는 데이터 속성인 data-delay를 사용하여 지연 시간을 가져옵니다.
- 주석 처리된 코드 블록은 스크롤 위치가 요소의 위치보다 크거나 같을 때, 해당 요소에 "show" 클래스를 추가하는 기능입니다. 여기서 window.innerHeight/2는 화면의 높이의 절반을 나타냅니다.
- 다음 코드 블록은 스크롤 위치가 요소의 위치보다 크거나 같을 때, "show" 클래스를 추가하는데, data-delay 속성이 정의되어 있다면 해당 지연 시간 후에 클래스를 추가합니다.
- requestAnimationFrame(scroll)은 애니메이션 프레임을 요청하여 scroll 함수가 연속적으로 호출되도록 합니다. 이로써 스크롤 이벤트가 발생할 때마다 요소가 업데이트됩니다.
- 마지막으로, 스크롤 위치를 화면에 표시하기 위해 .scroll span 요소의 내용을 업데이트합니다.
반응형