parallax 효과 만들기
메뉴
코드블럭
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>패럴랙스 이펙트01</title>
<link rel="stylesheet" href="css/reset.css">
<link rel="stylesheet" href="css/parallax.css">
</head>
<body class="img01 bg01 font01">
<header id="header">
<h1>Javascript parallax Effect01</h1>
<p>패럴랙스 이펙트: 메뉴 효과</p>
<ul>
<li class="active"><a href="parallaxEffect01.html">1</a></li>
<li><a href="parallaxEffect02.html">2</a></li>
<li><a href="parallaxEffect03.html">3</a></li>
<li><a href="parallaxEffect04.html">4</a></li>
<li><a href="parallaxEffect05.html">5</a></li>
<li><a href="parallaxEffect06.html">6</a></li>
</ul>
</header>
<!--header -->
<nav class="parallax__nav">
<ul>
<li class="active"><a href="#section1">메뉴1</a></li>
<li><a href="#section2">메뉴2</a></li>
<li><a href="#section3">메뉴3</a></li>
<li><a href="#section4">메뉴4</a></li>
<li><a href="#section5">메뉴5</a></li>
<li><a href="#section6">메뉴6</a></li>
<li><a href="#section7">메뉴7</a></li>
<li><a href="#section8">메뉴8</a></li>
<li><a href="#section9">메뉴9</a></li>
</ul>
</nav>
<!-- parallax__nav -->
<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">
<div class="parallax__item__img"></div>
</figure>
<p class="parallax__item__desc">결과도 중요하지만, 과정을 더 즁요하게 생각한다.</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">
<div class="parallax__item__img"></div>
</figure>
<p class="parallax__item__desc">세상 모든 일은 여러분이 무엇을 생각하느냐에 따라 일어납니다.</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">
<div class="parallax__item__img"></div>
</figure>
<p class="parallax__item__desc">웃음은 두 사람간의 가장 가까운 거리다</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">
<div class="parallax__item__img"></div>
</figure>
<p class="parallax__item__desc">지속적인 긍정적 사고는 능력을 배가시킨다.</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">
<div class="parallax__item__img"></div>
</figure>
<p class="parallax__item__desc">정의는 외부에서 오는 것이 아니라 내적 평온으로부터 온다.</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">
<div class="parallax__item__img"></div>
</figure>
<p class="parallax__item__desc">아무것도 변하지 않을지라도 내가 변하면 모든 것이 변한다</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">
<div class="parallax__item__img"></div>
</figure>
<p class="parallax__item__desc">노력을 이기는 재능은 없고 노력을 외면하는 결과도 없다</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">
<div class="parallax__item__img"></div>
</figure>
<p class="parallax__item__desc">사소한 것들을 소중히 해야한다. 그것이 삶을 이루는 버팀목이니까</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">
<div class="parallax__item__img"></div>
</figure>
<p class="parallax__item__desc">때론 기회를 놓치는 것이 기회일 수 있다.</p>
</section>
<!--//section9-->
</div>
</main>
<!-- main -->
<footer id="footer">
<a href="mailto:lee3ll@naver.com">lee3ll@naver.com</a>
</footer>
<aside class="parallax__info">
<div class="scroll">scrollTop : <span>0</span>px</div>
<div class="info">
<ul>
<li>#section1 offset() : <span class="offset1">0</span>px</li>
<li>#secrion2 offset() : <span class="offset2">0</span>px</li>
<li>#secrion3 offset() : <span class="offset3">0</span>px</li>
<li>#secrion4 offset() : <span class="offset4">0</span>px</li>
<li>#secrion5 offset() : <span class="offset5">0</span>px</li>
<li>#secrion6 offset() : <span class="offset6">0</span>px</li>
<li>#secrion7 offset() : <span class="offset7">0</span>px</li>
<li>#secrion8 offset() : <span class="offset8">0</span>px</li>
<li>#secrion9 offset() : <span class="offset9">0</span>px</li>
</ul>
</div>
</aside>
</body>
</html>
script 코드블럭
<script>
window.addEventListener("scroll", () => {
let scrollTop = window.pageYOffset //|| window.scrollY || document.documentElement.scrollTop;
document.querySelectorAll(".parallax__item").forEach((item, index) => {
if(scrollTop >= item.offsetTop -2){
// 메뉴바에서 모든 active 제거
document.querySelectorAll(".parallax__nav li").forEach((li) => {
li.classList.remove("active");
});
// active 활성화
document.querySelector(".parallax__nav li:nth-child("+(index+1)+")").classList.add("active");
}
});
document.querySelectorAll(".parallax__nav li a").forEach(li=>{
li.addEventListener("click", (e) => {
e.preventDefault();
document.querySelector(li.getAttribute("href")).scrollIntoView({
behavior:"smooth"
})
});
});
//info
const scroll = document.querySelector(".scroll span");
scroll.innerHTML = Math.floor(scrollTop); //Math.floor() // parseInt() 소수점 안보이게
// document.querySelector(".info .offset1").innerText = document.getElementById("section1").offsetTop;
// document.querySelector(".info .offset2").innerText = document.getElementById("section2").offsetTop;
// document.querySelector(".info .offset3").innerText = document.getElementById("section3").offsetTop;
// document.querySelector(".info .offset4").innerText = document.getElementById("section4").offsetTop;
// document.querySelector(".info .offset5").innerText = document.getElementById("section5").offsetTop;
// document.querySelector(".info .offset6").innerText = document.getElementById("section6").offsetTop;
// document.querySelector(".info .offset7").innerText = document.getElementById("section7").offsetTop;
// document.querySelector(".info .offset8").innerText = document.getElementById("section8").offsetTop;
// document.querySelector(".info .offset9").innerText = document.getElementById("section9").offsetTop;
});
const spans = document.querySelectorAll(".info span");
// for(let i=1; i<10; i++){
// document.querySelector(`.info .offset${i}`).innerText = document.getElementById(`section${i}`).offsetTop;
// };
// for문
// for(let i=0; i<=8; i++){
// spans[i].innerHTML = document.getElementById("section" + (i+1) ).offsetTop;
// }
// forEach 문
spans.forEach((el, i) => {
el.innerHTML = document.getElementById(`section${i+1}`).offsetTop;
});
// for in 문
// for(let index in spans){
// if(index.match(/[a-z]/) == null){
// spans[parseInt(index)].innerHTML = document.getElementById(`section${parseInt(index)+1}`).offsetTop;
// }
// }
// for of 문
// {
// let index = 0;
// for(let span of spans){
// span.innerHTML = document.getElementById(`section${index+1}`).offsetTop;
// index++;
// }
// }
</script>
보충설명
✨aside 태그: 오른쪽 사이드에 고정된 정보 영역입니다. 스크롤 위치를 나타내는 scrollTop과, 섹션들의 위치(offset) 정보를 보여주는 ul 태그로 구성되어 있습니다.
✨window.addEventListener: 윈도우 창이 스크롤될 때 발생하는 이벤트에 대한 리스너입니다.
✨document.querySelectorAll: 문서에서 지정한 모든 CSS 선택자를 가진 요소들을 찾습니다.
✨item.offsetTop: item이란 클래스명을 가진 요소의 맨 위쪽으로부터 떨어진 거리를 반환합니다.
✨if(scrollTop >= item.offsetTop -2): 현재 스크롤 위치가 item의 위치에서 2px 이상 내려간 경우
document.querySelectorAll(".parallax__nav li"): .parallax__nav 클래스를 가진 모든 li 요소를 찾습니다.
✨li.classList.remove: 해당 요소의 classList에서 'active' 클래스를 삭제합니다.
✨document.querySelector: CSS 선택자를 이용해 요소를 찾습니다.
✨li.getAttribute("href"): li 요소의 href 속성 값을 반환합니다.
✨document.querySelector(li.getAttribute("href")).scrollIntoView: href 값으로 지정된 요소를 찾아 브라우저 화면에서 보여지도록 스크롤합니다. 스크롤 애니메이션 효과를 적용합니다.
✨for문에서는 i라는 변수를 0부터 8까지 1씩 증가시키면서 spans라는 배열에서 i번째 span 요소를 선택하고, 그 요소의 innerHTML 값에 document.getElementById("section" + (i+1) ).offsetTop 값을 대입합니다. 이렇게 하면 spans[0]~spans[8]까지의 각각의 요소에 해당하는 section의 offsetTop 값을 출력하게 됩니다.
✨ forEach 문에서는 spans 배열의 각 요소를 el로, 해당 요소의 인덱스를 i로 받아옵니다. 그리고 각 요소의 innerHTML 값을 document.getElementById(section${i+1}).offsetTop 값으로 대체합니다. 이 코드는 for문과 같은 기능을 하지만, forEach 메서드를 사용하므로 더 간결하게 코드를 작성할 수 있습니다.