Vanilla JS Toy 프로젝트 - 2. Movie Seat Booking - CSS편(2)

falconlee236

·

2022. 3. 1. 22:21

반응형

여기에 올라온 모든 프로젝트와 소스코드는 here 여기서 확인할 수 있다.

vanilla javascript Toy project 2. Movie Seat Booking


웹 페이지 만들때 생각보다 js보다 css부분이 내용이 엄청 많다. 순전히 디자인적 요소만 들어가있어서 그런지 특히 속성 부분을 설명하는데 모든 시간을 쏟는거 같다. 그래서 이번 포스트는 css 2번째 부분이다.

4. showcase class 설정


showcase부분은 3가지 좌석 유형을 설명하는 부분이다. 이 부분을 우리는 li태그를 사용했는데, 이 못생긴 li태그를 어떻게 깔끔하게 만들 수 있는지 확인해보자.

  1. 일단 이 부분의 배경색과 글자 색이 각각 검은색, 회색이기 때문에 이것을 기본적으로 설정하고, padding을 적절히 설정해서 빈 여백을 만든다. 자세히 보면 사각형의 모서리가 둥글기 때문에 border-radius또한 필요하다.
  2. 그래도 li의 잔제가 남아있다. 바로 각 element에 있는 글머리 표시이다. 이것만 없애면 정말 깔끔할것 같다. 물론 이것도 css에서 속성으로 제어 가능하다.
    ✒️ list-style-type
    이 속성은 리스트 요소에 있는 글머리 표시를 설정할 수 있는 태그이다. 없애는 기능 이외에도 생각보다 많은 글머리 표시를 지원하고 있다. 여기서 값을 none으로 하면 글머리 표시를 없앤다.
  3. 리스트 요소가 한곳으로 계속 몰려있다. 이것은 어떻게 해야할까? 원소 하나하나마다 계속 여백을 설정해야할까? flex를 사용하면 해결된다. flex의 특징이 무엇일까? 바로 자동정렬이다. 심지어 justify-content속성을 사용하면 정렬 방식도 다르게 할 수 있다. 이 showcase 원소에 알맞는 정렬은 space-between이다.
    spacebetween이란?
  4. 리스트 요소에 있는 좌석 모양과 문자열도
    • display: flex
    • align-items: center
    • justify-content: center
      를 사용하면 가볍게 가운데 정렬이 가능하다.
  5. 코드는 다음과 같다
반응형

 

.showcase{ 
    background: rgba(0, 0, 0, 0.1); 
    padding: 5px 10px; 
    border-radius: 5px; 
    color: #777; 
    list-style-type: none; 
    display: flex; 
    justify-content: space-between; 
} 

.showcase li{ 
      display: flex; 
      align-items: center; 
      justify-content: center;
      margin: 0 10px; 
}

.showcase li small{ 
      margin-left: 2px;
}

 

 

5. container 내부 설정


이번 프로젝트의 container부분은 스크린과 좌석 배열이 있는 부분이다. 내가 처음에 이 프로젝트를 봤을때 가장 어려워보였던 부분이 이것이고 실제로 많은 css 기법이 들어가 있는 부분이었다. 이 부분을 공부하면서 css에 대해서 더 알아가보자.

  1. 현재 containter에 있는 기울어져 보이는 스크린 어떻게 만들까?
    • 처음 내가 생각한 방법은 사다리꼴을 만들어보자는 것이었다. div태그에 있는 여러가지 그림 그리기 속성을 사용해서 여러 그림을 만들 수 있었고, border-left, border-right와 같은 여러가지 속성을 사용했다.<내가 처음 스크린을 만든 코드>'
.screen{
	height: 0;
    width: 200px;
    border-top: 50px solid white;
    border-left: 5px solid transparent;
    border-right: 5px solid transparent;
    box-shadow: 0px 0px 5px white;
    margin: 30px 0;
}

 

 

  • 그런데 모범답안에서는 그냥 평범하게 스크린 사각형을 만든다. 그렇게 해서는 그냥 평평한 직사각형이 만들어지지 않나?
    • css에서는 객체 요소에 여러 변형을 가할 수 있는 transform 속성을 가지고 있다. transform속성에는 수많은 값을 가질 수 있는데, 이 스크린은 뭔가 기울어져 있으니까 회전을 해야하지 않을까? 따라서 회전하는 속성인 rotate를 사용한다.
      • ✒️ transform: rotate(90deg) -> rotate() 안에있는 값만큼 회전한다. 이때 값이 양수이면 시계방향으로, 음수이면 반시계방향으로 회전한다. 단위는 deg(각도)
    • 그런데 그냥 rotate를 사용하면 내가 원한 결과값이 아니다. 왜 그럴까? css에서 그냥 rotate를 사용하면 2차원 평면을 기준으로 시계방향, 반시계방향으로 움직이기 때문이다.
    • 내가 원하는 안쪽으로 들어가고 싶은 그런 모양은 어떻게 해결할까? 그럴때 바로 3차원이 필요한 것이다.
      • css에서 3차원 축을 설정하려면 사전 작업이 필요한데, 바로 perspective속성이다. perspective속성을 사용하면 원근감을 설정할 수 있고, 이 설정을 한 요소와 그 하위 요소들까지 전부 3차원 축이 적용이 된다.
        • ✒️ perspective: 1000px -> 속성 값만큼 원근감을 적용한다. 값이 클수록 멀리서 보는 느낌이 난다.
      • css에서 3차원 축은 다음과 같다.

따라서 우리가 원하는 스크린 방향을 만들기 위해서는 X축을 조절하면 된다는 것을 알 수 있고, 이 속성은 transform: rotateX()를 사용한다.
-   정리하자면 3차원축을 기준으로 모양을 조절하고 싶다면 해당 요소나, 해당 요소의 부모 요소에 perspectvie속성을 정의하고 그 다음에 해당 요소에 transform 속성을 적용하면 된다.

반응형

 

 


-   코드는 다음과 같다.
-  .container{
	perspective: 1000px;
    margin-bottom: 30px;
   }
   
   .screen{ 
   		background-color: #fff;
        height: 70px;
        width: 100%;
        margin: 15px 0;
        transform: rotateX(-45deg);
        box-shadow: 0 3px 10px rgba(255, 255, 255, 0.7); 
    }`

6. 좌석 레이아웃


containter class에 있는 수많은 좌석들, 이것을 어떻게 배치해야할까? 그 고민에 대한 답이 여기 있다.

  1. html파일을 보면 row class에 총 8개의 seat클래스가 있도록 배치를 했다. 이걸 어떻게 정렬할까? 정렬? 이쯤되면 감이 올 것이다. 그냥 row class에 flex속성을 부여한다면 자동으로 정렬이 된다!
  2. 이제 좌석중에서 왼쪽에서 2번째, 오른쪽에서 2번째 부분만 자리를 띄우면 좌석 레이아웃 완성이다. 어떻게 해야할까? html구조를 잘 보면 seat클래스 끼리는 서로 형제이다. 즉 8개 형제가 서로 붙어있는 꼴이다. 각 8개 좌석은 서로 row라는 클래스로 잘 묶어져 있으니 그러면 매 row마다 앞에서 2번째, 뒤에서 2번째 요소를 골라서 각각 margin을 오른쪽, 왼쪽 주면 될것 같다. 이제 질문은 하나이다. 어떻게 형제 요소를 고르지?
    • 이 질문에 대한 답을 해결해 주는게 가상클래스 이다.
      ✒️ pseudo-class :nth-of-type(n)
      서로 같은 유형을 가진 태그중에서 앞에서부터 n번째 형제를 선택하는 가상클래스이다. 이때 선택하는게 n번째 형재라는 점이 중요하다. 이 가상클래스와 비슷한게 :nth-last-of-type(n)이고, 이 가상클래스는 뒤에서 부터 n번재 형제를 선택한다.
    • .seat:nth-of-type(2){
        margin-right: 18px;
      }
      이런식으로 css를 정의한다면 모든 seat형제 중에서 2번째 형제의 오른쪽 margin을 18만큼 떨어뜨린다.
  3. 여기까지만 설정한다면 좌석 배열은 완료했을 것이다. 이제는 비어있는 좌석/선택된 좌석에 커서를 올리면 pointer cursor가 되고, 살짝 확대가 되는 부분을 구현해보자.
    • 이제 새로운 난관에 봉착을 한다. 어떻게 이미 차지하고 있는 좌석을 피해서 선택자를 적용해야할까? 나는 처음에 자식 선택자를 사용해서 선택자를 적용했다. 하지만 항상 더 나은 방법은 존재한다. 더 똑똑하고 범용성이 넓은 선택자를 사용해보자.
    • 한 태그에 클래스가 여러개 적용되어 있을때
      ✒️ pseudo-class :not(p)
      의사 클래스가 가리키는 대상에 class=p가 적용되어 있지 않는 태그를 선택한다.
      .seat:not(.occupied):hover 만약 이렇게 선택자가 있다면 다음과 같이 해석하면 된다.
      1. seat라는 클래스를 가지고 있는 태그 중에서
      2. occupied라는 클래스를 가지고 있지 않는 태그에
      3. 커서가 위로 올라갈 경우
    • 커서를 바꾸기 위해서는 cursor속성을 사용하면 되고
      • cursor: pointer -> 커서를 손모양으로 바꾼다.
      • cursor: default -> 커서를 기본 삼각형 모양으로 바꾼다.
    • 크기를 살짝 키우는 방법은 뭐가 있을까? 이전에 설명했던 transform 속성을 사용하면 좋다.
      ✒️ property transfrom: scale(n)
      해당 태그에 있는 요소를 n배 크게 한다.
      따라서 1.2배 크게 하고 싶으면 scale(1.2)를 하면 되고, 원상태로 되돌리고 싶으면 scale(1)을 하면 된다.
    • 여기까지 따라왔다면 코드는 다음과 같다.
반응형

 

.row{
	display: flex;
 } 
 
 
 .seat:nth-of-type(2){
 	margin-right: 18px;
  }
  
  .seat:nth-last-of-type(2){
  		margin-left: 18px;
  }
  
  .seat:not(.occupied):hover{
  		cursor: pointer;
        transform: scale(1.2);
  } 
  
  .showcase .seat:not(.occupied):hover{
  	cursor: default;
    transform: scale(1);
   }

 

7. 맨 마지막 텍스트 부분


이 텍스트 부분에서 딱히 설명할 것은 없다. 하지만 몇가지 짚고 넘어가야할 점을 알아보자.

  1. div vs p
    div태그와 p태그는 서로 하는 기능이 완벽히 같은 태그이다. 그런데 왜 이 둘을 나누어 놓았을까?
    💎 p tag
    <p>태그는 문자 정보를 입력하는 단락을 구성한다. 따라서 <p>태그 하위에는 다른 블록 요소가 포함되서는 안된다. <p>태그의 하위에는 <span>, <a>, <strong>과 같은 인라인 요소만 올 수 있다.
    💎 div tag
    <div> 태그는 HTML문서의 영역별 구분이다. 각 영역의 용도를 구분하는 기능이기 때문에 다른 블록 요소가 하위에 포함될 수 있다.
    • 즉 정리하자면 텍스트 정보는 <p> 태그 안에 작성하고, 그 밖에 다른 영역을 나누는 용도로는 <div>태그를 겹쳐서 사용한다.
    • 우리는 맨 마지막에 텍스트 정보를 사용하기 때문에태그를 사용했다.
  2. span태그?
    텍스트 중간에 파란색으로 칠해진 부분이 있다. 이 부분만 따로 선택하고 싶다면 태그를 따로 설정해야 한다. 텍스트 중간에 따로 클래스를 지정해서 여러가지를 하고 싶다면 span태그를 사용하는 것이 좋다.

여기까지 따라왔다면 코드는 다음과 같다.

<p class="text">
    You have selected 
    <span id="count">0</span> 
    seats for a price of $
    <span id="total">0</span>
</p> 
반응형