본문 바로가기
Today I Learned/JS

[JS] isotope.js - 에이블런 프론트엔드부트캠프 16일차

by YES_developNewbie 2024. 8. 6.

더보기

HTML

<body>
<header>
  <h1>DIAMOND</h1>

  <ul>
    <li>
      <a href="#">
        <i class="fab fa-facebook"></i>
        <span>FB</span>
      </a>
    </li>
    <li>
      <a href="#">
        <i class="fab fa-instagram"></i>
        <span>IG</span>
      </a>
    </li>
    <li>
      <a href="#">
        <i class="far fa-envelope"></i>
        <span>E-mail</span>
      </a>
    </li>
  </ul>
</header>
<main>
 <!-- 분류버튼  -->
  <ul class="btns">
    <li class="on"><a href="*">ALL</a></li>
    <li><a href=".odd">ODD</a></li>
    <li><a href=".even">EVEN</a></li>
  </ul>
  <section>
    <article class="odd">
      <div>
        <img src="img/p1.jpg" alt="">
        <h2>Lorem, ipsum dolor.</h2>
        <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Non, fugiat!</p>
      </div>
    </article>
    <article class="even">
      <div>
        <img src="img/p2.jpg" alt="">
        <h2>Lorem, ipsum dolor.</h2>
        <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Mollitia?</p>
      </div>
    </article>
    <article class="odd">
      <div>
        <img src="img/p3.jpg" alt="">
        <h2>Lorem, ipsum dolor.</h2>
        <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Non, fugiat!</p>
      </div>
    </article>
    <article class="even">
      <div>
        <img src="img/p4.jpg" alt="">
        <h2>Lorem, ipsum dolor.</h2>
        <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Non, fugiat!</p>
      </div>
    </article>
    <article class="odd">
      <div>
        <img src="img/p5.jpg" alt="">
        <h2>Lorem, ipsum dolor.</h2>
        <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Non, fugiat!</p>
      </div>
    </article>
    <article class="even">
      <div>
        <img src="img/p6.jpg" alt="">
        <h2>Lorem, ipsum dolor.</h2>
        <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Non, fugiat!</p>
      </div>
    </article>
    <article class="odd">
      <div>
        <img src="img/p7.jpg" alt="">
        <h2>Lorem, ipsum dolor.</h2>
        <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Non, fugiat!</p>
      </div>
    </article>
    <article class="even">
      <div>
        <img src="img/p8.jpg" alt="">
        <h2>Lorem, ipsum dolor.</h2>
        <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Non, fugiat!</p>
      </div>
    </article>
    <article class="odd">
      <div>
        <img src="img/p9.jpg" alt="">
        <h2>Lorem, ipsum dolor.</h2>
        <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Non, fugiat!</p>
      </div>
    </article>
    <article class="even">
      <div>
        <img src="img/p10.jpg" alt="">
        <h2>Lorem, ipsum dolor.</h2>
        <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Non, fugiat!</p>
      </div>
    </article>
    <article class="odd">
      <div>
        <img src="img/p11.jpg" alt="">
        <h2>Lorem, ipsum dolor.</h2>
        <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Non, fugiat!</p>
      </div>
    </article>
    <article class="even">
      <div>
        <img src="img/p12.jpg" alt="">
        <h2>Lorem, ipsum dolor.</h2>
        <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Non, fugiat!</p>
      </div>
    </article>
    <article class="odd">
      <div>
        <img src="img/p13.jpg" alt="">
        <h2>Lorem, ipsum dolor.</h2>
        <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Non, fugiat!</p>
      </div>
    </article>
    <article class="even">
      <div>
        <img src="img/p14.jpg" alt="">
        <h2>Lorem, ipsum dolor.</h2>
        <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Non, fugiat!</p>
      </div>
    </article>
    <article class="odd">
      <div>
        <img src="img/p15.jpg" alt="">
        <h2>Lorem, ipsum dolor.</h2>
        <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Non, fugiat!</p>
      </div>
    </article>
    <article class="even">
      <div>
        <img src="img/p16.jpg" alt="">
        <h2>Lorem, ipsum dolor.</h2>
        <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Non, fugiat!</p>
      </div>
    </article>
    <article class="odd">
      <div>
        <img src="img/p17.jpg" alt="">
        <h2>Lorem, ipsum dolor.</h2>
        <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Non, fugiat!</p>
      </div>
    </article>
    <article class="even">
      <div>
        <img src="img/p18.jpg" alt="">
        <h2>Lorem, ipsum dolor.</h2>
        <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Non, fugiat!</p>
      </div>
    </article>
    <article class="odd">
      <div>
        <img src="img/p19.jpg" alt="">
        <h2>Lorem, ipsum dolor.</h2>
        <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Non, fugiat!</p>
      </div>
    </article>
    <article class="even">
      <div>
        <img src="img/p20.jpg" alt="">
        <h2>Lorem, ipsum dolor.</h2>
        <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Non, fugiat!</p>
      </div>
    </article>
  </section>
</main>

</body>

 

SCSS

@import url('https://fonts.googleapis.com/css2?family=Orbitron:wght@400..900&display=swap');
@import 'reset.scss'; 

body{
  background: #efefef;
}

header{
  width:400px; height:100vh; 
  position: fixed; top: 0; left: 0; 
  background: linear-gradient(45deg, aqua, royalblue);
  //제목 
  h1{
    font:bold 50px/1 'Orbitron'; 
    color:#fff; 
    letter-spacing:1px; 
    position: absolute; 
    top:50%; left:50px;  
    transform:translateY(-150%); 
    
    //제목하단 텍스트 
    &::before{
      content:'UI/UX DEVELOPEMENT'; 
      display: block; 
      font:14px/1 'Orbitron'; color:#fff; 
      letter-spacing: 2px;
      position: absolute; 
      left: 0; top: 140px;
      opacity:0.8;  
    }
    //제목하단 라인 
    &::after{
      content:''; 
      display: block; 
      width: 140px; height: 2px; 
      background: #fff;  
      margin-top: 40px;
    }
  }

  ul{
    position: absolute; bottom: 100px; left: 50px;

    li{
      float:left; margin-right: 10px; 

      a{
        font-size:20px; color:#fff; 

        span{
          //transform적용하기위해서 block처리하면 줄바꿈되므로 inline-block으로 처리 
          display:inline-block;
          //글씨크기 줄이고 아이콘옆으로 살짝 이동
          transform:scale(0.7) translateX(-10px);
          opacity:0.7; 
        }
      }
    }
  }
}
main{
  margin-left: 400px;
  padding:20px; 

  //분류버튼 
  .btns{
    display: flex; gap: 10px;
    justify-content: flex-end;

    li {      
        a{ 
          display: block;
          padding: 10px; 
          font:bold 7px/1 'Orbitron'; 
          color:#aaa;  
          background: #fff; 
          border-radius: 5px; 
          box-shadow: 0px 0px 10px rgba(0,0,0,0.05);
      }
      //li에 on이 붙어 활성화되었을때 a태그상태 
      &.on a{
        background: linear-gradient(45deg, aqua, royalblue);
        color:#fff; 
        box-shadow: 0px 0px 5px rgba(0, 255, 255, 0.5);
      }
    
    }
  }


  section{
    width:100%; 
    
    article{
      width: 25%; float:left; 
      padding: 12px; 

      div{
        width: 100%; 
        background: #fff;
        border-radius: 4px;
        box-shadow:5px 5px 10px rgba(0,0,0,.1); 
        padding: 14px;

        img{
          width: 100%;
        }
        h2{
          margin-top: 15px; 
          margin-bottom: 5px; 
          font:bold 11px/1 'Orbitron'; 
          letter-spacing: 1px;
          color:#444;  
        }
        p{
          font:10px/1.2 'arial'; color: #777;
          margin-bottom: 15px;
        }
      }
    }
  }
}
//위쪽 원본은 1600px이상인 브라우저에서 실행 

//최대너비가 1599px인 브라우저크기까지는 
//안쪽의 코드 실행 
@media screen and (max-width:1599px){
  header{
    width:350px; 

    ul li{
      margin-right: 0;
    }
  }
  main{
    margin-left:350px; 
  }
}

@media screen and (max-width:1199px){
  header{
    width: 100%; height:80px; 
    position: relative; 

    h1{
      font:bold 24px/1 'Orbitron'; 
      transform: translateY(-50%);
      //header높이가 작아져서 꾸밈부분은 안보이게 처리 
      &::before{ display: none; }
      &::after{ display: none; }
    }
    //sns 리스트 
    ul{
      right:50px; bottom:25px; 
      left:auto; //원본에서 지정했던 left값 초기화

      li{
        margin-right: 20px; 
        a{
          span{ display: none;} 
          //텍스트 안보이게 처리
        }
      }
    }
  }
  main{
    margin-left:0; 
  }
}

@media screen and (max-width:899px){
  main section article{ width:33.333%;}
}

@media screen and (max-width:699px){
  main section article{ width:50%;}
}

@media screen and (max-width:539px){
  main section article{ width:100%;}

  header ul { display: none; }
}

1. ISOTOPE

isotope.js는 필터 기능 및 정렬 기능을 제공해주는 플러그인이다. 흔히 보는 갤러리 형식을 isotope를 활용해 개발할 수 있다.

 

isotope를 활용해 구현 가능한 레이아웃

 

isotope를 활용해서 갤러리 레이아웃을 개발하였다.

먼저, HTML에 isotope.js의 cdn을 선언해주었다.

 <script src="https://unpkg.com/isotope-layout@3/dist/isotope.pkgd.min.js"></script>

 

그리고 main 요소 안에 분류 버튼들과 이미지 article들을 작성해주었다.

 <!-- 분류버튼  -->
  <ul class="btns">
    <li class="on"><a href="*">ALL</a></li>
    <li><a href=".odd">ODD</a></li>
    <li><a href=".even">EVEN</a></li>
  </ul>
  <section>
    <article class="odd">
      <div>
        <img src="img/p1.jpg" alt="">
        <h2>Lorem, ipsum dolor.</h2>
        <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Non, fugiat!</p>
      </div>
    </article>
    <article class="even">
      <div>
        <img src="img/p2.jpg" alt="">
        <h2>Lorem, ipsum dolor.</h2>
        <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Mollitia?</p>
      </div>
    </article>
    <article class="odd">
      <div>
        <img src="img/p3.jpg" alt="">
        <h2>Lorem, ipsum dolor.</h2>
        <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Non, fugiat!</p>
      </div>
    </article>
    <article class="even">
      <div>
        <img src="img/p4.jpg" alt="">
        <h2>Lorem, ipsum dolor.</h2>
        <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Non, fugiat!</p>
      </div>
    </article>
    ...
  </section>
</main>

 

js에서는 isotope 환경설정 및 필터 코드를 작성해주었다

먼저 isotope 클래스를 생성하고 환경설정을 해주었다.

var elem = document.querySelector('section'); //컨테이너박스 
var iso = new Isotope( elem, { //컨테이너 박스명 
  // options
  itemSelector: 'article', //나란히 배치하는요소명 
  percentPosition: true, //아이템의 너비가 고정너비가 아닐때 
  masonry: {
    // use element for option
    columnWidth: 'article'//너비값 구할 요소명 
  }, 
  transitionDuration :'0.5s'//화면 재배치시 요소의 움직이는 속도 
});

 

버튼을 on 클래스를 넣는 방식으로 활성화하도록 구현하였고 Isotope.arrange 함수를 활용해서 정렬 기능을 구현하였다.

//버튼을 클릭했을 때 소팅 기능 구현 
//클릭한 버튼 활성화 
const btns = document.querySelectorAll(".btns li"); 
for(let btn of btns){
  btn.addEventListener("click", e=>{
    e.preventDefault(); 
    //모든 버튼에 on을 제거하고 
    for(let el of btns){
      el.classList.remove("on"); 
    }
    //현재 클릭한 버튼에만 on을 추가하여 활성화 
    e.currentTarget.classList.add("on"); 
    //클릭한 버튼의 자식요소인 a태그에서 href값을 변수에 저장 
    const sort = e.currentTarget.querySelector("a").getAttribute("href"); 

    //iso에 저장된 결과값을 불러와서 옵션값에 따라서 재정렬하기 
    iso.arrange({
      filter:sort //a태그의 href값에 따라서 재정렬 
    }); 
  })
}