Beautiful CSS

CSS Animation : 3D Transform

CSS3 : 3D Transform

Visual Design and Art School Logo Academy of Art University Logo
Related :

교육 카드 개설 현황

Channels :
Units :
Draft :

사이드바 2

Meta Info:

  • 2016년 8월 3일
  • Hyunhwa Jeong
  • 11,691 Views
  • 5 Comments

Table of Contents

CSS3 : 3D Transform

이 게시물은 2017년 2월 2일 수정판입니다.

이야기에 앞서

이 문서에서는 CSS3의 3D Transform 메소드를 사용해서 3차원 공간과 객체를 표현하는 방법에 대해 설명합니다. 학습의 연계성을 위해 이 문서를 읽기 전에 CSS3 : 2D Transform 혹은 웹 애니메이션 파헤치기 기사를 먼저 읽으시길 권합니다.


발동 조건

3D Transform은 애니메이션 속성이 아니므로 별도의 발동이 없습니다. 정의된 속성이 곧바로 화면에 적용되어 나타나며,:hover와 같은 가상 클래스 선택자(Pseudo-Classes) 혹은, 자바스크립트의 onclick 이벤트 따위의 부수적인 액션에 의해 변화를 발생시킬 수 있습니다.

또한, Transition이나 Animation 속성을 통해 움직임을 줄 수 있습니다.


CSS 구문

3D Transform 역시 2D Transform과 마찬가지로, 속성이 가지고 있는 값들을 쉼표 없이 나열하는 것으로 끝입니다. 다만 입체적인 움직임을 표현 할 몇 가지 메소드가 추가되었습니다.

.myclass { transform: translateZ(1000px) scaleZ(100%); }

3D Transform 메소드 정리

3D Transform 메소드 정리
메소드 설명
translate3d(x,y,z) 객체의 위치를 가로(x), 세로(y), 깊이(z) 방향으로 정의하여 이동시킵니다. 단위로는 px, %, em 따위를 사용할 수 있습니다. 예를들어, translate(60px, 60px, 60px)은 객체를 우측으로 60px, 하단으로 60px, 그리고 사용자와 60px만큼 가까운 위치로 이동시킵니다. 또한, 양수와 음수를 사용할 수 있습니다. 더 자세한 내용은 추후 기술합니다.
translateX(n) 객체의 위치를 가로 방향으로만 이동시킵니다. translateX(100px)은 우측으로 100px만큼 이동합니다. -100px과 같이 음수로 기재하면 반대방향인 좌측으로 100px만큼 이동합니다.
translateY(n) 객체의 위치를 세로 방향으로만 이동시킵니다. -100px과 같이 음수로 기재하면 반대방향인 상단으로 100px만큼 이동합니다.
scale3d(x,y,z) 객체의 세 방향을 한번에 늘이거나 줄일 수 입니다.
scaleX(n) 객체를 x축 중심으로 늘이거나 줄입니다.
scaleY(n) 객체를 y축 중심으로 늘이거나 줄입니다.
scaleZ(n) 객체를 z축 중심으로 늘이거나 줄입니다. CSS에는 두께라는 개념이 없습니다.
rotate3d(x,y,z) 객체의 세 방향을 한번에 회전 시킵니다.
rotateX(n) X축을 중심으로 객체를 회전시킵니다. 아래 종합예제에서 보여줍니다.
rotateY(n) Y축을 중심으로 객체를 회전시킵니다. 아래 종합예제에서 보여줍니다.
rotateZ(n) 2D Transform의 Rotate와 동일합니다.
perspective(n) 객체를 바라보는 원근을 입니다. 화면을 바라보는 사용자로부터 얼마나 멀리에 위치하는가를 나타냅니다.px을 사용하며, 수치가 낮을수록 가깝기 때문에 왜곡도 심하게 일어납니다. 자세한 내용은 추후 다시 설명합니다.
matrix3d(nx16) 2D Transform에서 알아봤듯이, 모든 값을 한번에 지정할 수 있지만, 16개의 값이 존재하며, 여기서 다룰 수 없는 영역입니다.

종합예제

이 종합예제에서는 2D Transform과 동일한 효과를 나타내는 메소드는 제외하고, 3D Transform 고유의 특징을 보여주는 부분에 대해서만 작성하였습니다. 또한, 3차원 공간을 표현하기 위한 새로운 축, Z가 추가되었기 때문에, 이 축을 활용하기 위한 별도의 CSS 속성도 추가로 정의해 주어야 합니다. 아래 예문을 보면서 천천히 살펴봅니다. 예제를 함께 따라 해 보고 싶다면 아래의 HTML과 CSS를 똑같이 작성하세요.

HTML

<div class="myClass"></div>

CSS

.myClass {
    width: 32px;
    height: 32px;
    background-color:#000;
    transition: transform 1s ease;
}

작은 네모를 하나 만들고, transition에서 transform 속성이 변화하도록 구문을 작성하였습니다. 이제 마우스를 올렸을 때 변화할 .myClass:hover 클래스를 정의해 주면 되는데, 아래의 예제를 보면서 하나씩 작성하며 테스트 해보세요.


.myClass:hover {
  transform: translateX(60px);
}
translateX
.myClass:hover {
  transform: translateY(60px);
}
translateY
.myClass:hover {
  transform: perspective(150px) translateZ(60px);
}
translateZ
.myClass:hover {
  transform: rotateX(45deg);
}
rotateX
.myClass:hover {
  transform: rotateY(45deg);
}
rotateY
.myClass:hover {
  transform: rotateZ(45deg);
}
rotateZ
.myClass:hover {
  transform: scaleX(2);
}
scaleX
.myClass:hover {
  transform: scaleY(2);
}
scaleY
.myClass:hover {
  transform: perspective(300px) scaleZ(3) translateZ(60px)
}
scaleZ

z축에 대한 이해

위 예문에서 translateXtranslateY는 2D Transform과 별반 다르지 않습니다. 표기하는 방법만 다를 뿐 표현되는 방식은 마찬가지입니다. 하지만 세 번째 예제인 translateZ는 조금 다릅니다. 이것은 마치 scale(n) 메소드를 사용한 것 처럼 보이지만, 실제로는 객체 자체의 크기가 커진 것이 아니라, 객체가 여러분 가까이 다가왔기 때문에 커져 보이는 것 입니다. translateZ는 객체의 크기를 조절하는 것이 아니라, 사용자와의 거리를 나타낸다는 점만 유의하면 됩니다.

이와같이, 3D Transform에서는 z축이 존재하기 때문에 몇 가지 추가적인 조건들이 존재합니다.

예를들어, 위 종합예제 중에서 translateZ를 다시한번 살펴보세요. 선언된 코드를 보면 transform: perspective(150px) translateZ(60px)으로 되어 있습니다. translateZ(60px) 이외에도 perspective(150px) 속성이 함께 선언되어 있습니다. 만일 이 속성이 선언되지 않았다면, 객체는 아무런 변화가 일어나지 않습니다. translateZ(60px)이란, 객체가 관찰자(나)로부터 60px 거리에 떨어져 있다는 뜻인데, 이 거리감을 표현하려면 나와 객체 사이의 거리를 나타내는 perspective 속성이 반드시 필요하기 때문입니다.

이 부분이 난해하다고 생각되면 그냥 넘어가세요. 이런 것들은 나중에 실제로 문제에 부딪혔을 때 다시 찾아보면 됩니다.


CSS3 Transform 속성

종합예제에서 3차원 변형을 만드는 각종 메소드(method)들을 알아보았는데, 이러한 변형을 위해 필요한 3D 전용 속성에 대해 알아야 합니다.

Perspective (원근)

종합예제에서 사용했던 translateZ 메소드를 사용하면, 그 자체만으로는 아무런 움직임도 얻을 수 없습니다. 예문에서는 z축으로 60px을 움직이기 위해 추가적인 속성 1개를 더 사용했는데, 바로 perspective입니다. 3D Transform에서 가장 중요한 요소는 transform과 perspective 속성입니다. 이 두 가지 속성 중 1개라도 선언이 안되면 정확한 효과를 줄 수 없습니다.

.myClass:hover {
  transform: perspective(150px) translateZ(60px);
}

위와 같이 단일 객체에 속성을 선언할 수 있고, 혹은 여러 객체를 품고 있는 부모 요소에 한번만 선언해서 그 자식 객체들이 모두 동일한 원근에 속하게 할 수도 있습니다. 소실점(Vanishing Point) 공유에 대한 이해가 필요한데, 지금은 넘어가고 밑에서 다시 알아봅니다.

<!-- HTML -->
<div>
    <p>자식 객체입니다</p>
    <p>자식 객체입니다</p>
    <p>자식 객체입니다</p>
</div>

<!-- CSS -->
div {
    width: 300px;
    height: 100px;
    perspective: 150px
}
div > p { transform: translateZ(150px) }

 

원근 속성을 부모 객체에 선언하는 것과, 아니면 각각의 객체에 개별적으로 선언하는 것은 큰 차이가 있습니다. 아래의 그림을 보고 이해해 보세요.


perspective-parent-child
이 그림은 Fabricio Rosa Marques의 기사 CSS3 Transforms by Example 에서 인용하였습니다.

아래 그림은, perspective 속성의 수치별 적용 사례입니다. 값이 작을수록 객체가 사용자와 가깝기 때문에 왜곡이 더 심하게 일어납니다. 아직까지도 perspective에 대해 난해한 감이 있는 분은 David DeSandroIntro to CSS 3D transforms - Example 3을 꼭 참고하세요. 아주 직관적으로 이해할 수 있습니다.

perspective-value
이 그림은 Fabricio Rosa Marques의 기사 CSS3 Transforms by Example 에서 인용하였습니다.

perspective-origin

원근의 시작점을 x와 y축으로 선언할 수 있습니다. 즉, 3차원 공간에 소실점을 설정하는 것과 같은 의미인데, 이 개념이 난해하다면 원근감의 기본 1점 소실점 구도를 읽어보면 쉽게 이해할 수 있습니다.

그래도 더 이해가 필요하다면, Intro to CSS 3D transforms - Example 3에서 버튼을 눌러서 회전을 중지시키고, perspective-orgin Xperspective-orgin X 슬라이더를 움직여보면 그 효과를 확실히 알 수 있습니다.

perspective-origin 속성은 반드시 perspective 속성과 함께 적용해야 효과를 볼 수 있는데, Intro to CSS 3D transforms - Example 3에서 perspective 값을 70px 정도로 낮춰보면 그 이유를 알 수 있습니다. perspective의 값이 낮을수록 소실점이 더욱 명확히 드러납니다.


perspective-origin은 객체 하나하나에 속성을 선언하는 것이 아니라, 모든 객체를 품고 있는 부모 객체 하나에만 선언하면 됩니다. 선언은 다음과 같이 합니다.

.camera {
    perspective: 70px;
    perspective-orgin: 50% 50%
}

perspective-orgin: 50% 50%에서 첫 번째 50%는 x축(수평)의 위치, 두 번째 50%는 y축(수직) 위치입니다. x, y 모두 각각 50%이므로 .camera에 포함된 모든 자식 객체는 정 중앙에 소실점을 갖는 원근 형태로 보여지게 됩니다. 글로 설명하려니 복잡한 것이고, 지금까지 예제 링크와 아래 이미지를 참고한다면 그 뜻을 이해할 수 있을 겁니다.

객체를 다양한 화각으로 바라보는 이미지
perspective-origin example image by Hyunhwa Jung

x와 y의 값으로는 % 이외에도 포지션 값(top, right, bottom, left, center), 길이 값(px, em, rem.. 기타)을 쓸 수 있습니다.


transfomr-style

transform-style 속성은, 자식 객체를 3차원 공간에서 어떻게 표현할 지 선택할 수 있습니다. flatpreserve-3d가 있으며, 기본 값은 flat입니다.

아래 예제에서 CSS를 살펴보면, .parent 객체에 transform-style: flat이라고 선언 된 부분입니다. 이렇게, 부모 요소에 flat을 선언하거나 혹은 아무것도 선언하지 않게 되면, 그 자식 요소에 해당하는 .child는 3D 공간 값을 가지지 못하므로, 아무리 transform: rotateX(-30deg)가 선언되어 있어도 표현되지 않습니다.




이번에는 부모 요소인 .parent 객체에 transform-style: preserve-3d를 선언했습니다. 이제 자식 객체인 .child는 부모와 같은 3D 영역을 공유하기 때문에, transform: rotateX(-30deg) 선언이 작동하게 됩니다. 부모가 뒤를 향하여 45도 각도로 회전했지만, 자식은 부모의 각도를 기본 각도로 인식합니다. 이 상태에서 자식 요소는 선언에 의해 다시 앞쪽으로 30도가 회전한 것을 보여줍니다.


backface-visibility

3D에서는 상당히 중요한 부분을 차지하는 개념입니다. 객체의 뒷면이 보이지 않도록 하는 속성인데, 좀 더 풀어서 표현하자면, 사용자의 시점에서는 보이지 않을 부분을 말그대로 보이지 않도록 처리합니다.

.myClass:hover {
  transform: rotateY(45deg);
}
rotateY
.myClass:hover {
  transform: rotateY(45deg);
  backface-visibility: hidden
}
rotateY and backface-visibility: hidden

첫 번째 예제는 backface-visibility 속성이 선언되지 않은 기본 값 visible입니다. 그래서 180도 회전 후에 뒷면이 보여집니다. 여기서 말하는 뒷면은 실제 뒷면이 아니라는 사실이 중요합니다. 뒷면이라는 것이 존재하려면 반대로 앞면이라는 것이 있어야 하는데, 예제에서는 div 태그가 단 하나밖에 사용되지 않았기 때문에 실제로는 앞면만 존재합니다. 말 그대로 앞면의 뒷쪽이라고나 할까요?

backface-visibility는 단순히 뒷면을 의미하는 것이 아니라, 객체의 보이지 않는 부분을 뜻한다는 점에 유의하세요.

오른 쪽 예제는 backface-visibility 속성에 hidden 값을 선언했습니다. 그래서 객체가 180도 회전하면, 뒤쪽에 해당하는 부분이 아예 보이지 않게 됩니다. 원래 이 객체 자체가 div 태그 하나로 이루어져 있기 때문에, 뒷면이라는 것 자체가 없기 때문에 화면상에 아무것도 나타나지 않는 것입니다.

글로 설명하는 것에는 한계가 느껴지긴 합니다만, 여기서 말하는 뒷면(실제로 면이 뒤에 있다는 것)뒷쪽(실제 면이 없고 개념상의 뒷부분)의 개념이 다르다는 점을 유의해 주시면 됩니다.

그렇다면, 오른 쪽 예제에서 뒷쪽에 아무것도 나타나지 않는 게 아니라, 다른 면을 보여주고 싶으면 어떻게 할까요? 새로운 div를 겹쳐 놓으면 됩니다. 실제 뒷면의 역할을 할 div 태그를 만드는 것이죠. 여기를 클릭해서 예제를 확인해 보세요.

마지막으로, backface-visibility 속성을 완전하게 이해할 수 있도록 Intro to CSS 3D transforms - Example 3에서 버튼을 눌러보세요.


마치며

이 문서의 처음에도 언급했지만, 3D Transform 속성 그 하나하나의 기능만 단편적으로 사용해서는 큰 효과를 보기 힘듭니다. 웹에서 객체의 변형을 통제하고 애니메이션을 제작하는 일련의 재료들로 생각하고, 큰 개념파악 정도만 하고 있으면 됩니다.

대부분은 이 속성들을 사용해서 제작된 다른 라이브러리나 플러그인을 사용하게 될텐데, 그때, 플러그인을 좀 더 자기 입맛에 맞게 수정할 수 있다면, 그것이 이 문서에서 여러분께 바라는 성취량입니다.

Subscribe
Notify of
guest
5 Comments
Inline Feedbacks
View all comments
박성진

개념정리도 잘되있고 좋네요 감사히 읽고, 링크 좀 담아가겠습니다.

DM Kim

정리가 잘 되어 있어서 이해하기 정말 쉽네요 홈페이지 ui도 마음에 드네요 자주 들어올것 같아요..
이 글은 퍼갑니다.

beautifulcss

네 공부 열심히 하세요~ 조금 난해한 파트인데 이해가 가셨더니 기분이 좋네요~

Stella Park

좋은 글 감사합니다. 퍼가요~

beautifulcss

네 공부 열심히요~