본문 바로가기

Front-end Developer

Udemy - P50 Projects In 50 Days - HTML, CSS & JavaScript

728x90

kdt 코딩온 하면서 같은 팀프로젝트 했던 조원분이 정말 좋은 강의영상을 추천해 줬다.

바로 50일간 프로젝트를 하면서 직접 코드를 쓰면서 배우는 것이다.

이 강의가 "정말 좋겠다!"라고 생각하게 된 계기는 밑에 짤로 설명이 가능할 거 같다.

 

 

 

코드를 짜놓고 보면 어디서 무엇이 어떻게 작동하는지 모를뿐더러 어떤 원리로 작동을 하는지 이론으로는 한계가 있다고 느꼈다.

직접 프로젝트를 하면서 다양하게 활용하면서 부족했던 부분은 기록하는 것이 좋다고 생각하여 50일간 프로젝트 공부를 하게 됐다. 

그럼 시작해 보자. 추천해 주신 우리 https://sunddaegguk.tistory.com/28 님 정말 감사합니다. :)

 

[포스코X코딩온]웹개발자 풀스택 과정 4주차 3일까지 회고록 7

오오 드디어 프로젝트. 학교다닐 때는 초중고 때는 뭐랬더라 까먹었고 대학때는 조별과제 혹은 팀플이라고 그랬지. 그 때도 뭐 수십번하고 발표하고 맨날 하고 일하면서도 맨날 프로젝트하고

sunddaegguk.tistory.com

 

1일 차 스타트!  (1/50)


 

 

 


카드 형태의 프로필을 만들어서 각 카드를 선택하면 이미지가 넓어지는 프로젝트이다. 

Flexbox로 모든 걸 정렬하고 그런 다음 javascript를 이용하여 이 중 하나를 클릭하면 클래스가 활성화되어 CSS 전환으로 확장한다.

 

 


HTML 작성

 

 

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <!-- fontawesom (scdnjs) mdn -->
    <link
      rel="stylesheet"
      href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.2/css/all.min.css"
      integrity="sha512-z3gLpd7yknf1YoNbCzqRKc4qyor8gaKU1qmn+CShxbuBusANI9QpRohGBreCFkKxLhei6S9CQXFEbbKuqLg0DA=="
      crossorigin="anonymous"
      referrerpolicy="no-referrer"
    />

    <link rel="stylesheet" href="style.css" />

    <title>Expanding Cards</title>
  </head>
  <body>
    <div class="container">
      <div
        class="panel active"
        style="
          background-image: url('https://images.unsplash.com/photo-1558979158-65a1eaa08691?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1350&q=80');
        "
      >
        <h3>Explore The World</h3>
      </div>
      <div
        class="panel"
        style="
          background-image: url('https://images.unsplash.com/photo-1572276596237-5db2c3e16c5d?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1350&q=80');
        "
      >
        <h3>Wild Forest</h3>
      </div>
      <div
        class="panel"
        style="
          background-image: url('https://images.unsplash.com/photo-1507525428034-b723cf961d3e?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1353&q=80');
        "
      >
        <h3>Sunny Beach</h3>
      </div>
      <div
        class="panel"
        style="
          background-image: url('https://images.unsplash.com/photo-1551009175-8a68da93d5f9?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1351&q=80');
        "
      >
        <h3>City on Winter</h3>
      </div>
      <div
        class="panel"
        style="
          background-image: url('https://images.unsplash.com/photo-1549880338-65ddcdfd017b?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1350&q=80');
        "
      >
        <h3>Mountains - Clouds</h3>
      </div>
    </div>

    <script src="script.js"></script>
  </body>
</html>

 

 

HTML은 비교적 간단하다 

1. 5개의 div(. panel)을 관리할 div(. container)를 작성한다. 

2. container 내부에 5개의 div(. panel)를 생성한다.

3. 각각의 div(. panel)에게 style="background-img: url()"을 사용하여 배경이미지를 넣는다.

 

 

HTML 끝

 

완성된 HTML의 모양이다 지금부터 CSS로 꾸며주기 시작하자.

 


CSS 작성

 

@import url("https://fonts.googleapis.com/css?family=Muli&display=swap");

* {
  box-sizing: border-box;
}

body {
  font-family: "Muli", sans-serif;
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100vh;
  overflow: hidden;
  margin: 0;
}

/* 모든 패널(div)을 감싸고 있는 */
.container {
  display: flex;
  width: 90vw;
}
.panel {
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  height: 80vh;
  border-radius: 50px;
  color: #fff;
  cursor: pointer;
  /* 각각의 패널들 크기는 0.5씩 */
  flex: 0.5;
  margin: 10px;
  /* h3태그를 absolute 주기위함 */
  position: relative;
  transition: flex 0.7s ease-in;
}
.panel h3 {
  font-size: 24px;
  position: absolute;
  bottom: 20px;
  left: 20px;
  margin: 0;
  opacity: 0;
}

.panel.active {
  flex: 5;
  transition: opacity 0.3s ease-in 0.4s;
}
.panel.active h3 {
  opacity: 1;
}
@media (max-width: 480px) {
  .container {
    width: 100vw;
  }
  .panel:nth-of-type(4),
  .panel:nth-of-type(5) {
    display: none;
  }
}

 

 

1. body 

 

body {
  font-family: "Muli", sans-serif;
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100vh;
  overflow: hidden;
  margin: 0;
}

 

- body 태그 먼저 살펴보자

 

- display: flex를 사용하여 body 내부에 있는 div들이 모두 flex 컨테이너로 설정하도록 했다..

- font-family: 속성은 본문의 글꼴을 "Muli"로 설정하고, sans-serif로 대체하여 사용하도록 했다.

- align-items: 속성은 중앙 정렬을 위해 center로 설정하였다.

- justify-content: 속성은 중앙 정렬을 위해 center로 정렬하였다.

- height : 본문의 높이를 브라우저 뷰포트(브라우저 창의 높이)의 100%로 설정하였다.

- overflow: 내부 내용이 뷰포트(브라우저의 창)를 벗어날 경우 스크롤바를 숨기도록 하였다.

- margin: 모든 방향 (위, 아래, 왼쪽, 오른쪽)의 마진을 0으로 설정하여, 본문 주위의 여백을 없앴다.

 


 

2. container

 

 

.container {
  display: flex;
  width: 90vw;
}

 

- display:. container에서도 마찬가지로 display: flex를 사용하여 자식요소들을 flex 컨테이너로 설정하였다.

- width: 90vw를 사용하여 전체 넓이를 90vw (90%)만 사용하도록 했다.

 


 

3.panel

.panel {
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  height: 80vh;
  border-radius: 50px;
  color: #fff;
  cursor: pointer;
  /* 각각의 패널들 크기는 0.5씩 */
  flex: 0.5;
  margin: 10px;
  /* h3태그를 absolute 주기위함 */
  position: relative;
  transition: flex 0.7s ease-in;
}

 

각각의 div(. panel)의 CSS를 살펴보자

 

1. background-size: cover -> 각 이미지가 div(. panel)에 꽉 차도록 cover을 사용했다.

2. background-position: center -> 이미지의 포커싱이 중앙으로 향하도록 설정했다.

3. background-repeat: no-repeat -> div(. panel) 크기가 커져도 이미지가 반복되지 않도록 no-repeat사용

4. height: 80vh -> 각각의 높이는 80vh(80%) 설정

5. border-radius: 50px -> 박스의 모서리 부분은 50px을 사용하여 조금 둥글게 만들었다.

6. color: #fff -> 이미지 내부에 있는 h3태그의 글자색은 하얀색으로 설정

7. cursor: pointer -> 마우스를 이미지에 올리면 손가락 모양 포인터 설정

8. flex: 0.5 -> 각각의 flex크기를 0.5씩 동일하게 나눴다.

9. position: relative -> 이미지 내에 있는 h3를 absolute를 사용하여 자유롭게 설정하기 위해 relative설정

10. transition: flex 0.7s ease-in -> flex 속성 변경 시 부드러운 애니메이션 효과를 0.7초 동안 진행되도록 적용한다.

 


 

4. panel h3 

 .panel h3 {
  font-size: 24px;
  position: absolute;
  bottom: 20px;
  left: 20px;
  margin: 0;
  opacity: 0;
}

 

각각의 이미지 내에 있는 h3 스타일링

 

1. font-size: 24px -> 글자 크기는 24px

2. position: absolute -> absolute를 사용하여 panel 기준으로 자유롭게 움직일 수 있도록 설정

3. bottom: 20px -> 글자위치는 밑에서 20px 떨어지도록 설정

4. left: 20px -> 글자위치는 왼쪽에서 20px 떨어지도록 설정

5. margin: 0 -> 글자에 마진을 모두 0px

6. opacity: 0 -> 글자를 숨겨놓는다. 나중에 애니메이션으로 나타나게 하도록


 

5. .panel.active

 

  flex: 5;
  transition: opacity 0.3s ease-in 0.4s;

 

나중에 javascript 를통해 active 클래스가 추가되었을 때 작동하도록 미리 설정한 css

 

flex: 5; -> 액티브가 추가되면 flex사이즈는 5개의 패널 중 크기가 5를 갖도록 한다.

transition: opcity 0.3s ease-in 0.4s -> 액티브가 추가되면 애니메이션 작동하도록 설정

 

6. .panel.active h3 

  opacity: 1;

 

여긴 간단하다 위에서 우리는 active 클래스가 생기기 전에 opacity를 0으로 설정하였다.

이것은 active class가 추가되면 opacity를 1로 설정하여 다시 나타나도록 하였다.

 


 

7.media Query

 

@media (max-width: 480px) {
  .container {
    width: 100vw;
  }
  .panel:nth-of-type(4),
  .panel:nth-of-type(5) {
    display: none;
  }
}

 

미디어쿼리 사용하였다. 너비가 480px 이하로 줄어들면 container의 너비는 100vw을 사용하며,

5개의 div(.panel) 박스 중 4번째 5번째 div(.panel)은 display: none을 사용하여 숨기도록 하였다.

 


Javascript 

 

const panels = document.querySelectorAll(".panel");

panels.forEach((panel) => {
  panel.addEventListener("click", () => {
    removeActiveClasses();
    panel.classList.add("active");
  });
});

function removeActiveClasses() {
  panels.forEach((panel) => {
    panel.classList.remove("active");
  });
}

 

1. const panels = document.querySelectorAll(".panel");

-> 문서 내의 class명이 panel을 가지고 있는 요소를 모두 가져온다.

 

panels.forEach((panel) => {
  panel.addEventListener("click", () => {
    removeActiveClasses();
    panel.classList.add("active");
  });
});

 

2. panels라는 배열의 각 요소에 대해 반복 작업을 수행한다.

panels 배열은 DOM 요소로 이루어진 패널들의 리스트를 가지고 있다.

각각의 배열을 순회하면서 패널 요소에 대한 클릭 이벤트에 대한 이벤트 리스너를 추가한다.

이벤트리스너는 사용자가 클릭하면 작동하도록 한다.

 

removeActiveClasses() 함수 호출: 클릭이벤트가 발생하면 먼저

removeActiveClasses() 함수를 호출하도록 한다. 이 함수는 패널들에서 active 클래스를 제거하는

역할을 한다. 이 함수는 active클래스를 제거하는 역할을 한다. 모든 패널에서

active클래스를 지우고 나서 하나의 패널에서만 active클래스를 추가한다.

 

panel.classList.add("active"); 클릭된 패널에 active클래스를 추가하도록 한다.

 

function removeActiveClasses() {
  panels.forEach((panel) => {
    panel.classList.remove("active");
  });
}

 

 

8. 최종 결과물

 

 

 


 

1일차 프로젝트 끝

하면서 느낀점 forEach를 까먹었다.. 다시 공부하러 가도록 한다.

처음 게시글이라 너무 뭔가 하나하나 설명을 적으면서 내려가다보니 게시글 시간이 너무 소요된다.

앞으로는 짧게 설명하고 모르는것만 작성하도록 해야겠다.

 

프로젝트하면서 결과물도 얻고 내가 부족한 부분을 바로 캐치하고 다시 복습할수 있어서 정말 좋은거같다.

내일도 화이팅이다.

728x90