본문 바로가기

CSS

CSS - 3D

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <style>
    .world {
      width: 60vw;
      height: 60vh;
      background: #fff000;
      display: flex;
      align-items: center;
      justify-content: center;
    }
    .card {
      display: flex;
      align-items: center;
      justify-content: center;
      width: 100px;
      height: 150px;
      margin:1em;
      /* 폰트사이즈에 비례해서 바뀔수있도록 em */
      border-radius: 0.5em;
      font-size: 1.5rem;
      background: red;
      transform: rotateY(45deg)
    }
  </style>
  <body>
    <div class="world">
      <div class="card">CARD</div>
      <div class="card">CARD</div>
      <div class="card">CARD</div>
    </div>
  </body>
</html>

 

위와같이 

roateY를 사용해서 축을 돌리게되면 y축으로 회전이 진행된다.

 

하지만 결과물은 전혀 3D스럽지 않다

 

이를 위해서 원근감속성을 줘야한다.

 

perspective

보이는 위치에 따라서 원근감을 주는 속성

얼만큼 내눈에서 멀리있는지 바라보는지 정해준다.

 

숫자가 가까워질수록 눈에 가까워진 느낌이라 생각하면된다. 

 

 

시점을 고정시켜서 보여주고 싶다면. (ex, 카드 게임) 

 

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <style>
    .world {
      width: 60vw;
      height: 60vh;
      background: #fff000;
      display: flex;
      align-items: center;
      justify-content: center;
      /* perspective: 500px; */
    }
    .card {
      display: flex;
      align-items: center;
      justify-content: center;
      width: 100px;
      height: 150px;
      margin:1em;
      /* 폰트사이즈에 비례해서 바뀔수있도록 em */
      border-radius: 0.5em;
      font-size: 1.5rem;
      background: red;
      transform:perspective(500px) rotateY(45deg) ;
      
    }
  </style>
  <body>
    <div class="world">
      <div class="card">CARD</div>
      <div class="card">CARD</div>
      <div class="card">CARD</div>
    </div>
  </body>
</html>

 

perspective 속성을 transform에 주게 되면 동일한 효과가 발생한다.

 

 

 

 

 

카드 스타일링하기

현재 앞면 뒷면이 같게 나온다. 

 

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <style>
    .world {
      width: 60vw;
      height: 60vh;
      background: #fff000;
      display: flex;
      align-items: center;
      justify-content: center;
      perspective: 500px;
    }
    .card {
      position: relative;
      width: 100px;
      height: 150px;
      margin: 1em;
      /* 폰트사이즈에 비례해서 바뀔수있도록 em */
      
      /* 기존 브라우저 렌더링시 0deg를 인식하면 해당 부분이 transform으로 움직일 준비를 시킨다 */
      transform: rotateY(0deg);
      transition: 1s;
    }
    .card-side {
      display: flex;
      align-items: center;
      justify-content: center;
      border-radius: 0.5em;
      font-size: 1.5rem;
      background: red;
      position: absolute;
      width: 100%;
      height: 100%;
      left: 0;
      top: 0;
    }
    .card-side-front{
        background: white;
        
    }
    .card-side-back{
        background: red;
    }
    
    .world:hover .card {
      transform: rotateY(180deg);
    }
  </style>
  <body>
    <div class="world">
      <div class="card">
        <div class="card-side card-side-front">F</div>
        <div class="card-side card-side-back">B</div>
      </div>
    </div>
  </body>
</html>

 

현재 상태로 진행을하면 

 

 

 

 

위와같이 코드를 짜게 되면 앞면 뒷면이 둘다 B부분만 나오게 된다. 

이에 해당하는 이유는  

 

position absolute를 활용해서 겹치게 되면 

앞 면과 뒷면이 붙어있는 상태가 아닌 

앞면과 앞면이 겹쳐있는 상태가 된다.

따라서 transform: rotateY를 통해 뒷면을 뒤집어 줘야한다.

 

또한 world에서 지정해준 perspective 속성을 card의 자식속성에도 전달해주기위해

transform-style을 사용한다. 

transform-style

  • flat 요소의 자식이 평면에 있음을 나타낸다(default)
  • preserve-3d 요소의 자식이 3D공간에 배치해야함을 나타낸다.

 

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <style>
    .world {
      width: 60vw;
      height: 60vh;
      background: #fff000;
      display: flex;
      align-items: center;
      justify-content: center;
      perspective: 500px;
    }
    .card {
      position: relative;
      width: 100px;
      height: 150px;
      margin: 1em;
      /* 폰트사이즈에 비례해서 바뀔수있도록 em */ 
      /* 기존 브라우저 렌더링시 0deg를 인식하면 해당 부분이 transform으로 움직일 준비를 시킨다 */
      transform: rotateY(0deg);
      transition: 1s;
      /* card  */
      transform-style: preserve-3d;
      /* 문의 축 설정 */
      transform-origin: 100% 0;
    }

    .card-side {
      display: flex;
      align-items: center;
      justify-content: center;
      border-radius: 0.5em;
      font-size: 1.5rem;
      background: red;
      position: absolute;
      width: 100%;
      height: 100%;
      left: 0;
      top: 0;
      /* 3d의 뒷면을 가릴때 사용 */
      backface-visibility: hidden;
    }
    .card-side-front{
        z-index: 1;
        background: white;     
    }
    .card-side-back{
        background: red;
        transform: rotateY(180deg);
    }
    .world:hover .card {
      transform: rotateY(-180deg);
    }
  </style>
  <body>
    <div class="world">
      <div class="card">
        <div class="card-side card-side-front">F</div>
        <div class="card-side card-side-back">B</div>
      </div>
    </div>
  </body>
</html>

 

문의 느낌을 내주기 위해 기존 center로 지정되어있던 3d 축을 

transform-origin을 사용해서 축을 변경시켜주고 

rotateY를 통해서 문을 열고 나가는 느낌을 만들어주었다.

 

 

 

 

 

 

 

위와같이 코드를 짜게 되면 이제 크롬에서는 정상 동작하나 

다른 브라우저들에서는 실행이 안되는경우들이 생긴다. 

이를 위해서 각 브라우저 개발자에서는 이를 위해 아래와같은 형태를 붙여준다.(실험적 기능)

-webkit-(사파리, 크롬)

-moz-(모질라)

-ms-(마이크로소프트)

-o-(오페라)

 

IE에서는 transform-style: preserver-3d가 적용이 되지 않는다. 

이를 위해서 속성을 통째로 바꿔줘야 한다.

 

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <style>
    .world {
      width: 60vw;
      height: 60vh;
      background: #fff000;
      display: flex;
      align-items: center;
      justify-content: center;
      perspective: 500px;
    }
    .card {
      position: relative;
      width: 100px;
      height: 150px;
      margin: 1em;
      /* 폰트사이즈에 비례해서 바뀔수있도록 em */ 
      /* 기존 브라우저 렌더링시 0deg를 인식하면 해당 부분이 transform으로 움직일 준비를 시킨다 */
      transform: rotateY(0deg);
      transition: 1s;
      /* card  */
      transform-style: preserve-3d;
      /* 문의 축 설정 */
      transform-origin: 100% 0;
    }

    .card-side {
      display: flex;
      align-items: center;
      justify-content: center;
      border-radius: 0.5em;
      font-size: 1.5rem;
      background: red;
      position: absolute;
      left: 50%;
      top: 50%;
      width: 100px;
      height: 150px;
      margin: -75px 0 0 -50px;
      /* 사파리 대응 */
      -webkit-backface-visibility: hidden;
      /* 3d의 뒷면을 가릴때 사용 
        맨 마지막엔 표준 속성이 나오는게 좋다.  
      */
      backface-visibility: hidden;
      transition: 1s;
    }
    .card-side-front{
        z-index: 1;
        background: white;     
    }
    .card-side-back{
        background: red;
        transform: rotateY(180deg);
    }
    .world:hover .card-side-front {
      transform: rotateY(180deg);
    }
    .world:hover .card-side-back {
      transform: rotateY(360deg);
    }
  </style>
  <body>
    <div class="world">
      <!-- <div class="card"> -->
        <div class="card-side card-side-front">F</div>
        <div class="card-side card-side-back">B</div>
      <!-- </div> -->
    </div>
  </body>
</html>

 

 

 

'CSS' 카테고리의 다른 글

CSS - Grid  (0) 2020.12.20
CSS - 3D 공간 만들기  (0) 2020.12.12
CSS - flex  (0) 2020.11.29
CSS - animation  (0) 2020.11.28
CSS- transform , transition  (0) 2020.11.27