Ted's Codding study

0미니프로젝트 - imageGallery-vanilaJS 본문

projects

0미니프로젝트 - imageGallery-vanilaJS

Ted93 2024. 5. 16. 07:32

깃허브 : https://github.com/SeungjuShin93/imageGallery-vanilaJS

데모 : https://seungjushin93.github.io/imageGallery-vanilaJS/

HTML과 CSS는 간략하게 다루고 자바스크립트 위주로 글을 작성하겠습니다

요약 : 이미지 5장을 가지고, 
서브 이미지 박스에서 이미지를 클릭하면 가운데 큰 이미지가
해당 클릭된 이미지로 바뀌는 이미지 갤러리 구현
추가적으로 다크 모드 버튼을 누르면 토글 버튼으로 써 다크 모드와 라이트 모드 구현

 

1. HTML

HTML 코드
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Image Gallery</title>
  <link rel="stylesheet" href="style.css">
  <script src="main.js" defer></script>
</head>
<body id="body">
  <div class="wrapper">
    <h1>Image Gallery Practice</h1>
    <div class="container">
      <div class="main-container">
        <div id="overlay" class="main-overlay"></div>
        <button id="main-btn" class="main-btn">다크 모드</button>
        <img id="main-img" src="images/cat01.jpg" alt="고양이1">
      </div>
      <div id="sub-container" class="sub-container">
        <img src="images/cat01.jpg" alt="고양이1">
        <img src="images/cat02.jpg" alt="고양이2">
        <img src="images/dog01.jpg" alt="강아지1">
        <img src="images/dog02.jpg" alt="강아지2">
        <img src="images/dog03.jpg" alt="강아지3">
      </div>
    </div>
  </div>
</body>
</html>
  • HTML 코드 설명
    1. 큰 틀로는, 전체를 감싸주는 박스를 wrapper로 만들어 줌
    2. 메인 이미지 박스와 서브 이미지 박스로 나누었음
    3. 메인 컨테이너에서 overlay는 다크 모드를 구현 시 어둡게 해주는 역할을 하는 박스임
    4. 메인 버튼은 다크 모드를 구현할 버튼
    5. 메인 이미지는 가장 크게 보일 이미지
    6. 서브 컨테이너 안의 이미지들은 밑에 클릭할 수 있는 이미지들임
    7. id로 선언된 것은 JS에서 DOM으로 활용할 요소들임을 암시
    8. class로 선언된 것은 CSS에서 스타일을 줄 요소들임을 암시

 

2. CSS

CSS 코드
body {
  margin: 0;
}

body.dark {
  background-color: rgba(0, 0, 0, 0.8);
  color: white;
}

.wrapper {
  width: 100%;
  height: 100vh;
  margin: auto;
  display: flex;
  justify-content: center;
  align-items: center;
  flex-direction: column;
  max-width: 1200px;
}
.wrapper h1 {
  font-size: 2rem;
  text-align: center;
}

.container {
  width: 50%;
  margin: 0 auto;
  overflow: hidden;
  border-radius: 5px;
}

.main-container {
  position: relative;
  width: 100%;
  height: 50vh;
}

.main-overlay {
  position: absolute;
  width: 100%;
  height: 100%;
  top: 0;
  left: 0;
  background-color: rgba(0, 0, 0, 0);
  color: black;
}

.main-btn {
  position: absolute;
  top: 2px;
  left: 3px;
  border: 1px solid #999;
  border-radius: 3px;
  width: 90px;
  padding: 10px 0;
  background-color: rgba(150, 150, 150, 0.6);
  color: black;
}
.main-overlay.dark,
.main-btn.dark {
  background-color: rgba(0, 0, 0, 0.5);
  color: white;
}
.main-container img {
  width: 100%;
  height: 100%;
}

.sub-container {
  display: flex;
  width: 100%;
}
.sub-container img {
  width: 20%;
}

@media (max-width: 1024px) {
  .container {
    width: 60%;
  }
  .wrapper h1 {
    font-size: 1.5rem;
  }
  .main-container {
    height: 40vh;
  }
}
@media (max-width: 768px) {
  .container {
    width: 70%;
  }
  .wrapper h1 {
    font-size: 1.2rem;
  }
  .main-container {
    height: 30vh;
  }
}

 

CSS 코드는 헷갈렸던 부분만 설명하겠습니다.

container 박스에 border-radius를 줬는데 처음에 작동하지 않았습니다.

그래서 생각했던 게 main-container 박스에서 아래와 같이

border-top-left-radius: 5px;
border-top-right-radius: 5px;

일일이 코딩을 했었습니다. 마찬가지로

sub-container 박스에 아래와 같이

border-bottom-left-radius: 5px;
border-bottom-right-radius: 5px;

주었었는데, 나중에 리팩토링을 하면서 학습을 통해서

그동안 다른 사람 코드에서 overflow:hidden이 왜 이리 많이 들어가나 싶었는데 (이론은 알고 있었지만 실제로 많은 페이지들을 인스펙션해서 overflow 속성을 지워도 차이를 못 느끼는 경우가 있어서 정확한 학습이 어려웠었음)

부모 컨테이너인 container에 border-radius를 주고 overflow:hidden;을 주면 된다는 것을 알게 되었습니다. overflow:hidden을 주기 전에는 자식 요소인 이미지가 모서리를 뚫고 나왔는데 이 옵션을 주게 되면 그 부분을 hidden 처리를 해주면서 원하는 방향으로 구현이 가능했다

요약하자면 아래 처럼만 하면 끝!

.container {
  overflow: hidden;
  border-radius: 5px;
}

3. JS

JS 코드
const body = document.getElementById('body');
const overlay = document.getElementById('overlay');
const mainBtn = document.getElementById('main-btn');
const mainImg = document.getElementById('main-img');
const subContainer = document.getElementById('sub-container');

mainBtn.addEventListener('click', darkMode);
subContainer.addEventListener('click', changeMainImg);

// dark 모드
function darkMode() {
  body.classList.toggle('dark');
  overlay.classList.toggle('dark');
  mainBtn.classList.toggle('dark');
  if (mainBtn.classList.contains('dark')) {
    mainBtn.textContent = '라이트 모드';
  } else {
    mainBtn.textContent = '다크 모드';
  }
}

// 그림 교체
function changeMainImg(e) {
  const src = e.target.src;
  const alt = e.target.alt;
  mainImg.src = src;
  mainBtn.alt = alt;
}

JS 코드 설명

다크모드 구현

메인 버튼을 클릭 시 다크 모드 함수 호출

  1. dark 클래스에 대한 CSS를 만들어 둘것
  2. mainBtn을 클릭했을 때 darkMode 함수를 실행하고 body, overlay, mainBtn에 ‘dark’ 라는 클래스 이름을 토글로 붙여줄 것 toggle은 스위치처럼 작동하며 클릭하면 dark 클래스가 생기고, 다시 클릭하면 dark 클래스가 없어짐
    mainBtn.addEventListener('click', darkMode);
    function darkMode() {
      body.classList.toggle('dark');
      overlay.classList.toggle('dark');
      mainBtn.classList.toggle('dark');
    }
  3. mainBtn에는 dark 모드가 적용되었을 때는 ‘라이트 모드’ 라는 글귀가 보이도록, dark 클래스가 없다면 ‘다크 모드’ 가 보이도록 할 것 contains는 dark글씨가 있다면 true를 반환, 없다면 false를 반환함
      if (mainBtn.classList.contains('dark')) {
        mainBtn.textContent = '라이트 모드';
      } else {
        mainBtn.textContent = '다크 모드';
      }

dark-mode

이미지 교체 구현

  1. 5개의 이미지가 담겨 있는 부모인 박스 subcontainer에 click 이벤트를 걸어주면 changeMainImg 함수를 호출
    subContainer.addEventListener('click', changeMainImg);
  2. changeMainImg 함수에는 이벤트를 인자인 e를 전달해주고 클릭된 이미지의 src 속성인 e.target.src 속성과 e.target.alt 속성을 const 변수인 src와 alt에 할당
  3. 할당된 src속성와 alt속성을 mainImg의 src와 alt에 각각 할당
    function changeMainImg(e) {
      const src = e.target.src;
      const alt = e.target.alt;
      mainImg.src = src;
      mainBtn.alt = alt;
    }

image-change

간단한 JS 코드로도 그럴듯한? (제 생각뿐인가요 하하)
미니 프로젝트를 구현해 보아서 매우 뿌듯합니다~~

 

노션으로 보고 싶다면?

https://short-echidna-b16.notion.site/imageGallery-vanilaJS-c2d13c4a4e5943509004927dfb036f02?pvs=4

 

미니프로젝트 - imageGallery-vanilaJS | Notion

깃허브

short-echidna-b16.notion.site