본문 바로가기
Tutorial/GSAP

10. GSAP Parallax Effect : 메뉴 축소 효과

by @webstoryboy 2023. 6. 20.
Tutorial/webd

GSAP 패럴랙스 이펙트 : 메뉴 축소 효과

by @webs 2023. 06. 01.
10
GSAP Parallax Effect : 메뉴 축소 효과
난이도 중간
소스 다운로드
완성 화면 소스 보기 유튜브

소개

안녕하세요! 웹스토리보이입니다. 메뉴 클릭에 있어 메뉴 확대 축소 효과를 완성해보겠습니다. 일반적으로 메뉴가 있다가 스크롤을 내리면 축소되거나 모바일 메뉴로 바꾸는 형태로 많이 사용합니다. 다시 처음으로 돌아오면 크게 확대되는 효과입니다. 스크립트와 CSS를 같이 사용하는 효과입니다. 비교적 사용빈도가 높고 쉽게 때문에 쉽게 따라할 수 있습니다. 그럼 바로 시작해보겠습니다. 🤪

1. 기본 구조 만들기

1-1. 준비하기

GSAP를 배우는 시간이기 때문에 HTML/CSS 코딩은 생략하겠습니다. 기본 코딩은 복사해서 사용하겠습니다. 우선 웹폰트를 설정하고 GSAP에서 필요한 파일을 미리 셋팅해 놓겠습니다. GSAP는 자주 업데이트가 되기 때문에 제일 최선 버전을 사용하는게 좋습니다.

<!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>GSAP Scroll Effect</title>

    <!-- 웹폰트 설정 -->
    <link href="https://webfontworld.github.io/NexonLv1Gothic/NexonLv1Gothic.css" rel="stylesheet">
    <link href="https://fonts.googleapis.com/css2?family=Lato:wght@100&display=swap" rel="stylesheet">
</head>
<body>

    <!-- GSAP 라이브러리 설정 -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.11.5/gsap.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.11.5/ScrollTrigger.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.1/ScrollToPlugin.min.js"></script>
</body>
</html>

1-2. 기본 셋팅하기

소스는 그대로 복사해서 사용하겠습니다.

<!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>GSAP Scroll Effect</title>

    <link href="https://webfontworld.github.io/NexonLv1Gothic/NexonLv1Gothic.css" rel="stylesheet">
    <link href="https://fonts.googleapis.com/css2?family=Lato:wght@100&display=swap" rel="stylesheet">
    <style>
        * {
            margin: 0;
            padding: 0;
        }
        a {
            color: #fff;
            text-decoration: none;
        }
        body {
            color: #fff;
            font-family: "NexonLv1Gothic";
            font-weight: 300;
            background-color: #333;
        }
        #parallax__title {
            position: fixed;
            left: 20px;
            top: 20px;
            z-index: 1000;
        }
        #parallax__title h1 {
            font-size: 30px;
            border-bottom: 1px dashed #fff;
            margin-bottom: 10px;
            padding-bottom: 5px;
            font-weight: 400;
            display: inline-block;
        }
        #parallax__title p {
            font-size: 16px;
        }
        #parallax__title ul {
            margin-top: 10px;
        }
        #parallax__title li {
            display: inline;
        }
        #parallax__title li a {
            width: 20px; 
            height: 20px;
            border-radius: 50%;
            border: 1px dashed #fff;
            display: inline-block;
            text-align: center;
            line-height: 20px;
            font-size: 12px;
        }
        #parallax__title li.active a {
            background: #fff;
            color: #000;
        }
        #parallax__nav {
            position: fixed;
            right: 20px;
            top: 20px;
            z-index: 1000;
            background-color: rgba(0,0,0,0.4);
            padding: 15px 20px;
            border-radius: 50px;
            text-align: center;
        }
        #parallax__nav li {
            list-style: none;
            display: inline;
        }
        #parallax__nav li a {
            display: inline-block;
            width: 80px; 
            height: 30px;
            padding: 5px;
            text-align: center;
            line-height: 30px;
            transition: all 0.3s;
        }
        #parallax__nav li a.active {
            background: #fff;
            color: #000;
            border-radius: 30px;
        }
        #parallax__nav.is-active li a {
            width: 30px; 
        }

        /* parallax__cont */
        #parallax__cont {
            max-width: 1600px;
            width: 98%;
            margin: 0 auto;
        }
        .parallax__item {
            width: 1000px;
            max-width: 70vw;
            margin: 30vw auto;
            text-align: left;
            margin-right: 0;
            position: relative;
            padding-top: 15vw;
        }
        .parallax__item:nth-child(even) {
            margin-left: 0;
            text-align: right;
        }
        .parallax__item__num {
            font-size: 35vw;
            position: absolute;
            left: -5vw;
            top: -13vw;
            opacity: 0.07;
            font-family: "Lato";
            font-weight: 100;
        }
        .parallax__item:nth-child(even) .parallax__item__num {
            left: auto;
            right: -5vw;
        }
        .parallax__item__title {
            padding-bottom: 5px;
            font-weight: 400;
        }
        .parallax__item__imgWrap {
            width: 100%;
            padding-bottom: 56.25%;
            background: #000;
            position: relative;
            overflow: hidden;
        }
        .parallax__item__img {
            position: absolute;
            left: -5%; 
            top: -5%;
            width: 110%;
            height: 110%;
            background-repeat: no-repeat;
            background-position: center center;
            background-size: cover;
            filter: saturate(0%);
            transition: all 1s;
        }
        .parallax__item__img:hover {
            filter: saturate(100%);
            transform: scale(1.025);
        }
        #section1 .parallax__item__img {
            background-image: url(assets/img/images01@2.jpg);
        }
        #section2 .parallax__item__img {
            background-image: url(assets/img/images02@2.jpg);
        }
        #section3 .parallax__item__img {
            background-image: url(assets/img/images03@2.jpg);
        }
        #section4 .parallax__item__img {
            background-image: url(assets/img/images04@2.jpg);
        }
        #section5 .parallax__item__img {
            background-image: url(assets/img/images05@2.jpg);
        }
        #section6 .parallax__item__img {
            background-image: url(assets/img/images06@2.jpg);
        }
        #section7 .parallax__item__img {
            background-image: url(assets/img/images07@2.jpg);
        }
        #section8 .parallax__item__img {
            background-image: url(assets/img/images08@2.jpg);
        }
        #section9 .parallax__item__img {
            background-image: url(assets/img/images09@2.jpg);
        }
        .parallax__item__desc {
            font-size: 4vw;
            line-height: 1.4;
            margin-top: -5vw;
            margin-left: -4vw;
            z-index: 100;
            position: relative;
            word-break: keep-all;
        }
        .parallax__item:nth-child(even) .parallax__item__desc {
            margin-left: auto;
            margin-right: -4vw;
        }
    </style>
</head>
<body>
    <header id="parallax__title">
        <h1>GSAP Parallax Effect10</h1>
        <p>GSAP scrollTrigger - 메뉴 축소 효과</p>
        <ul>
            <li><a href="gsap01.html">1</a></li>
            <li><a href="gsap02.html">2</a></li>
            <li><a href="gsap03.html">3</a></li>
            <li><a href="gsap04.html">4</a></li>
            <li><a href="gsap05.html">5</a></li>
            <li><a href="gsap06.html">6</a></li>
            <li><a href="gsap07.html">7</a></li>
            <li><a href="gsap08.html">8</a></li>
            <li><a href="gsap09.html">9</a></li>
            <li class="active"><a href="gsap10.html">10</a></li>
            <li><a href="gsap11.html">11</a></li>
            <li><a href="gsap12.html">12</a></li>
            <li><a href="gsap13.html">13</a></li>
            <li><a href="gsap14.html">14</a></li>
            <li><a href="gsap15.html">15</a></li>
        </ul>
    </header>
    <!-- //parallax__title  -->

    <nav id="parallax__nav">
        <ul>
            <li><a href="#section1" class="active">s1</a></li>
            <li><a href="#section2">s2</a></li>
            <li><a href="#section3">s3</a></li>
            <li><a href="#section4">s4</a></li>
            <li><a href="#section5">s5</a></li>
            <li><a href="#section6">s6</a></li>
            <li><a href="#section7">s7</a></li>
            <li><a href="#section8">s8</a></li>
            <li><a href="#section9">s9</a></li>
        </ul>
    </nav>
    <!-- //parallax__nav -->

    <main id="parallax__cont">
        <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 -->
    </main>

    <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.11.5/gsap.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.11.5/ScrollTrigger.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.1/ScrollToPlugin.min.js"></script>
    <script>
        
    </script>
</body>
</html>

2. 스크립트 작업하기

2-1. 작업하기

우선 #parallax__nav 선택자에 클래스 is-active가 있을 때, 없을 때 CSS 작업을 먼저 해주어야 합니다. 물론 이것도 GSAP로 가능하지만 CSS로 간단하게 할 수 있기 때문에 CSS로 작업하겠습니다. 중요한건 소스가 깔끔하고 보기 좋은게 좋거든요! 그리고 ScrollTrigger.create에서 스타트 값과 끝나는 값을 설정합니다. 끝나는 값은 99999로 임의의 값을 설정했습니다. toggleClass 속성을 이용하면 간단하게 메뉴 확대 축소 효과는 끝이 납니다. 수고하셨습니다^^ 😄

#parallax__nav li a {
    width: 80px; 
    transition: all 0.3s;
}
#parallax__nav.is-active li a {
    width: 30px; 
}
ScrollTrigger.create({
    start: "top -80",
    end: 99999,
    toggleClass: {
        className: "is-active", 
        targets: "#parallax__nav"
    }
});

3. 마무리

간단하게 CSS와 GSAP를 이용하여 작업해봤습니다. GSAP의 장점이 간단한 소스로 괜찮은 효과를 만들 수 있는게 매우 좋은 거 같습니다. 여러분들도 잘 따라해보고, 실제 사이트에 적용해 보면 아주 좋을 것 같습니다. 그럼 수고하셨습니다. 😱


예제 목록

댓글