CSS 변환 모듈 레벨 2

W3C 워킹 드래프트,

이 문서에 대한 추가 정보
이 버전:
https://www.w3.org/TR/2021/WD-css-transforms-2-20211109/
최신 공개 버전:
https://www.w3.org/TR/css-transforms-2/
에디터 드래프트:
https://drafts.csswg.org/css-transforms-2/
이전 버전:
히스토리:
https://www.w3.org/standards/history/css-transforms-2
이슈 추적:
CSSWG 이슈 저장소
명세 내 인라인
에디터:
Tab Atkins Jr. (Google)
L. David Baron (Google)
(Apple Inc)
(Apple Inc)
(Apple Inc)
피드백:
피드백은 GitHub에서 이슈를 등록하여 보내주세요 (권장), 명세 코드 “css-transforms”를 제목에 포함하여 다음과 같이 작성해 주세요: “[css-transforms] …코멘트 요약…”. 모든 이슈와 코멘트는 아카이브로 남습니다. 또는, 피드백은 (아카이브됨) 공개 메일링 리스트 www-style@w3.org로 보낼 수 있습니다.
이 명세 편집 제안:
GitHub 에디터
델타 명세:

개요

CSS 변환은 CSS로 스타일링된 요소를 2차원 또는 3차원 공간에서 변형할 수 있도록 합니다.

이 명세는 3차원 변환을 위한 새로운 변환 함수와 속성, 그리고 간단한 변환을 위한 편의 함수들을 추가합니다.

CSS는 구조화된 문서(예: HTML 및 XML)의 렌더링을 화면, 종이 등에서 설명하는 언어입니다.

이 문서의 상태

이 섹션은 이 문서가 발행된 시점의 상태를 설명합니다. 현재 W3C 발행물 목록과 이 기술 보고서의 최신 버전은 W3C 기술 보고서 색인 https://www.w3.org/TR/에서 확인할 수 있습니다.

이 문서는 CSS 작업 그룹에서 작업 초안으로 권고 경로를 사용하여 발행되었습니다.

작업 초안으로 발행된 것이 W3C 및 회원들의 승인이나 지지를 의미하지는 않습니다.

이 문서는 초안이며 언제든지 다른 문서로 업데이트, 대체 또는 폐기될 수 있습니다. 진행 중인 작업 외의 용도로 이 문서를 인용하는 것은 적절하지 않습니다.

이 문서는 2021년 11월 2일 W3C 프로세스 문서의 적용을 받습니다.

이 문서는 W3C 특허 정책에 따라 운영되는 그룹에 의해 작성되었습니다. W3C는 해당 그룹의 산출물과 관련하여 공개된 특허 공개 목록을 유지합니다; 해당 페이지에는 특허 공개 방법도 포함되어 있습니다. 특허의 실제 내용을 알고 있으며 해당 특허가 필수 청구항을 포함한다고 생각하는 개인은 W3C 특허 정책 6절에 따라 정보를 공개해야 합니다.

1. 소개

이 명세는 [css-transforms-1]을 확장하여 작성자가 요소를 3차원 공간에서 변형할 수 있도록 하는 델타 명세입니다. transform 속성에 대한 새로운 변환 함수들은 3차원 변환을 허용하며, 추가 속성들은 3차원 변환을 더 쉽게 다룰 수 있도록 하고, 작성자가 중첩된 3차원 변환 요소들의 상호작용을 제어할 수 있도록 합니다.

  1. perspective 속성은 작성자가 자식 요소에 추가적인 원근 변환을 제공할 수 있게 합니다. perspective-origin 속성은 원근이 적용되는 기준점을 제어하여 "소실점"의 위치를 효과적으로 변경할 수 있게 합니다.

  2. transform-style 속성은 3D 변환된 요소와 그 3D 변환된 자손들이 공통된 3차원 공간을 공유할 수 있게 하여, 3차원 객체의 계층 구조를 구성할 수 있도록 합니다.

  3. backface-visibility 속성은 요소가 3차원 변환을 통해 뒤집혀서 뒷면이 사용자에게 보일 때 작동합니다. 일부 상황에서는 이 때 요소를 숨기는 것이 바람직할 수 있으며, 이 속성에서 hidden 값을 사용하여 요소를 숨길 수 있습니다.

참고: transform 속성의 일부 값은 요소를 3차원 좌표계에서 변형할 수 있게 하지만, 요소 자체는 3차원 객체가 아닙니다. 대신 요소는 2차원 평면(평평한 표면) 위에 존재하며 깊이가 없습니다.

이 명세는 또한 scale, translate, rotate의 세 가지 편의 속성을 추가하여 간단한 변환을 더 쉽게 기술하고 애니메이션할 수 있습니다.

1.1. 모듈 상호작용

여기 정의된 3D 변환 함수transform 속성의 함수 집합을 확장합니다.

perspective, transform-style, backface-visibility의 일부 값은 모든 자손에 대한 포함 블록 및/또는 스태킹 컨텍스트 생성을 야기합니다.

3차원 변환은 요소의 시각적 레이어링에 영향을 주며, Appendix E ([CSS21])에 설명된 앞뒤 페인팅 순서를 덮어씁니다.

1.2. 값 정의

이 명세는 CSS 속성 정의 규약 ([CSS21])을 따르며, 값 정의 문법 ([CSS-VALUES-3])을 사용합니다. 이 명세에서 정의하지 않은 값 타입은 CSS Values & Units [CSS-VALUES-3]에서 정의됩니다. 다른 CSS 모듈과 결합하면 이러한 값 타입의 정의가 확장될 수 있습니다.

각 속성 정의에 명시된 속성별 값 이외에도, 이 명세에서 정의된 모든 속성은 CSS 전역 키워드를 속성 값으로 허용합니다. 가독성을 위해 반복해서 명시하지 않았습니다.

2. 용어

3D 변환된 요소

transform 속성의 계산 값에 3D 변환 함수 중 하나가 포함된 요소

3D 행렬

4x4 행렬로서 2D 행렬의 요건을 충족하지 않는 행렬입니다.

단위 변환 함수

CSS Transforms의 단위 변환 함수 외에도, 단위 변환 함수의 예로는 translate3d(0, 0, 0), translateZ(0), scaleZ(1), rotate3d(1, 1, 1, 0), rotateX(0), rotateY(0), rotateZ(0), matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1) 등이 있습니다. 원근(perspective)은 특별한 사례로 perspective(none)이 해당됩니다. m34의 값이 극히 작아지고, 변환 함수는 결과적으로 단위 행렬과 같다고 간주됩니다.

원근 행렬

perspectiveperspective-origin 속성의 값으로부터 아래에 설명된 방식으로 계산된 행렬입니다.

누적된 3D 변환 행렬

요소의 3D 렌더링 컨텍스트의 루트에 대해 상대적으로 아래에 설명된 방식으로 계산되는 행렬입니다.

3D 렌더링 컨텍스트

공통 조상을 가진 요소 집합으로, 아래에 설명된 방식으로 공통 3차원 좌표계를 공유합니다.

2.1. computed value<transform-list> 직렬화

<transform-list>computed value는 아래 알고리즘에 따라 하나의 <matrix()> 또는 <matrix3d()> 함수로 직렬화됩니다:

  1. transform을 단위 행렬로 초기화된 4x4 행렬로 둡니다. transform m11, m22, m33, m44 요소는 1로 설정하고, 나머지 transform의 요소들은 모두 0으로 설정합니다.

  2. <transform-function>들을 <transform-list>에서 transform에 모두 차례로 우측 곱(post-multiply)합니다.

  3. <matrix()> 또는 <matrix3d()> 직렬화 중 선택합니다:

    transform2D 행렬이라면
    transform<matrix()> 함수로 직렬화합니다.
    그 외의 경우
    transform<matrix3d()> 함수로 직렬화합니다.

이 텍스트를 CSS Transforms 1의 내용에 추가하도록 수정 필요.

3. 2차원 부분집합

UA는 항상 3차원 변환을 렌더링할 수 있는 것은 아니므로, 이 명세의 2차원 부분집합만 지원할 수 있습니다. 이 경우 3차원 변환transform-style, perspective, perspective-origin, backface-visibility 속성은 지원하지 않아야 합니다. 3D 변환 렌더링 섹션은 적용되지 않습니다. 행렬 분해는 "Graphics Gems II, edited by Jim Arvo"의 "unmatrix" 메서드에서 가져온 기법을 2D의 경우로 단순화하여 사용합니다. 변환 함수의 수학적 설명 섹션은 여전히 유효하지만 3x3 변환 행렬을 사용하여 a는 m11, b는 m12, c는 m21, d는 m22, e는 m41, f는 m42로 줄일 수 있습니다(6개 파라미터로 구성된 2D 3x2 행렬 참고).

$$\begin{bmatrix} a & c & e \\ b & d & f \\ 0 & 0 & 1 \end{bmatrix}$$

2차원 변환을 위한 3x3 행렬.

작성자는 UA가 3차원 변환을 지원하지 않을 경우 손쉽게 폴백을 제공할 수 있습니다. 아래 예시에서는 transform 속성에 두 가지 정의가 있습니다. 첫 번째는 두 개의 2차원 변환 함수로 구성되어 있습니다. 두 번째는 2차원 변환 함수와 3차원 변환 함수가 함께 있습니다.

div {  transform: scale(2) rotate(45deg);
  transform: scale(2) rotate3d(0, 0, 1, 45deg);
}

3D 지원이 있을 경우, 두 번째 정의가 첫 번째를 덮어씁니다. 3D 지원이 없으면 두 번째 정의는 무효이며 UA는 첫 번째 정의로 폴백합니다.

4. 변환 렌더링 모델

이 명세는 CSS Transforms 1 § 3 변환 렌더링 모델을 확장하여 3차원 변환 함수의 존재, transform-origin의 Z 값, perspective 속성, 그리고 transform-style 속성의 사용 값이 preserve-3d일 때 적용되는 새로운 3D 렌더링 모델을 다룹니다.

3차원 변환 함수는 좌표 공간을 개념적으로 3차원으로 확장하며, 화면 평면에 수직인 Z축을 추가하고, Z축의 값은 사용자 쪽으로 증가합니다.

초기 좌표 공간 데모

초기 좌표 공간의 데모.

3D 변환에서는 transform-origin의 Z 성분이 결과에 영향을 주므로, 변환 행렬transformtransform-origin 속성으로 다음과 같이 계산됩니다:

  1. 단위 행렬로 시작합니다.

  2. transform-origin의 계산된 X, Y, Z 값만큼 이동(translate)합니다.

  3. transform 속성에 있는 각 변환 함수를 왼쪽에서 오른쪽 순서로 곱합니다.

  4. transform-origin의 계산된 X, Y, Z 값을 부호를 반대로 하여 이동(translate)합니다.

4.1. 3D 변환 렌더링

일반적으로 요소는 평면으로 렌더링되며, 자신의 stacking context와 동일한 평면에 렌더링됩니다. 대부분의 경우 이는 페이지의 나머지 부분과 공유하는 평면입니다. 2차원 변환 함수는 요소의 모양을 변경할 수 있지만, 그 요소는 여전히 stacking context와 같은 평면에 렌더링됩니다.

3차원 변환이 적용된 요소가 3D 렌더링 컨텍스트에 포함되어 있지 않으면, 해당 변환만 적용되어 렌더링되지만 다른 요소와 교차하지는 않습니다. 이때의 3차원 변환은 2차원 변환처럼 단순한 페인팅 효과로 간주할 수 있습니다. 마찬가지로, 변환은 페인팅 순서에 영향을 주지 않습니다. 예를 들어, Z축에 양의 값을 변환하면 요소가 더 커 보일 수 있지만, Z 변환이 없는 요소 앞에 렌더링되지는 않습니다.

중첩된 3D 변환 요소의 렌더링 방식(수식 등 포함) 설명 필요

이 예시는 앞서 나온 텍스트와 연결되지 않음.

이 예시는 요소에 3차원 변환이 적용된 효과를 보여줍니다.

<style>
div {
    height: 150px;
    width: 150px;
}
.container {
    border: 1px solid black;
}
.transformed {
    transform: rotateY(50deg);
}
</style>

<div class="container">
    <div class="transformed"></div>
</div>
rotateY 변환이 적용된 div.

이 변환은 수직인 Y축을 기준으로 50° 회전입니다. 파란 박스가 더 좁아보이지만, 3차원적으로 보이진 않는 점에 주목하세요.

4.1.1. 원근(perspective)

원근(perspective)은 Z축에서 더 위쪽(사용자에게 더 가까움)에 있는 요소를 더 크게, 더 멀리 있는 요소를 더 작게 보이게 하여 장면에 깊이감을 더할 수 있습니다. 스케일링은 d/(dZ)에 비례하며, 여기서 dperspective 속성의 값으로, 도면 평면에서 사용자 눈의 위치까지의 거리입니다.

원근 효과는 3D 변환된 요소에 두 가지 방법으로 적용할 수 있습니다. 첫째, 요소의 'transform function list'에 perspective() 함수가 포함되어 있으면 해당 함수가 요소의 'current transformation matrix'로 계산됩니다.

둘째, perspectiveperspective-origin 속성을 요소에 적용하여 3D 변환된 자식의 렌더링에 영향을 줄 수 있으며, 이들은 동일한 3차원 장면에 존재하는 것처럼 보이도록 공유된 원근을 제공합니다.

스케일과 Z 위치의 관계 다이어그램

perspective 속성과 Z 위치에 따라 스케일링이 어떻게 달라지는지 보여주는 다이어그램. 위 다이어그램에서는 Zd의 절반입니다. 원래 원(실선)이 Z(점선 원)에 나타나도록 하려면 원을 두 배로 확대해야 하며, 그 결과 연한 파란색 원이 됩니다. 아래 다이어그램에서는 원이 1/3만큼 축소되어 원래 위치 뒤에 나타납니다.

일반적으로 사용자의 눈 위치는 그림의 중앙에 있다고 가정합니다. 이 위치는 필요에 따라 조정할 수 있습니다. 예를 들어, 웹 페이지에 여러 그림이 있어 공통 원근을 공유해야 할 경우 perspective-origin을 설정하면 됩니다.

다른 perspective-origin의 다이어그램

원근 기준점을 위로 이동했을 때의 효과를 보여주는 다이어그램.

원근 행렬은 다음과 같이 계산됩니다:

  1. 단위 행렬로 시작합니다.

  2. perspective-origin의 계산된 X, Y 값만큼 이동(translate)합니다.

  3. perspective() 변환 함수에서 얻은 행렬을 곱합니다. 길이는 perspective 속성의 값으로 제공합니다.

  4. perspective-origin의 계산된 X, Y 값을 부호를 반대로 하여 이동(translate)합니다.

이 예시는 원근을 사용하여 3차원 변환이 더 현실적으로 보이게 하는 방법을 보여줍니다.

<style>
div {
  height: 150px;
  width: 150px;
}
.container {
  perspective: 500px;
  border: 1px solid black;
}
.transformed {
  transform: rotateY(50deg);
}
</style>

<div class="container">
  <div class="transformed"></div>
</div>
컨테이너에 perspective가 적용된 rotateY 변환 div

내부 요소는 이전 예시와 동일한 변환을 사용하지만, 이제 부모 요소의 perspective 속성에 의해 렌더링이 영향을 받습니다. Perspective는 Z 좌표가 양수(사용자에게 가까운)인 꼭짓점은 X, Y 방향으로 확대되고, Z 좌표가 음수(멀리 있는)는 축소되어 깊이감을 줍니다.

4.1.2. 3D 렌더링 컨텍스트

이 섹션은 3D 변환과 transform-style 속성을 사용하는 콘텐츠의 렌더링 모델을 규정합니다. 이 모델을 설명하기 위해 "3D 렌더링 컨텍스트"라는 개념을 도입합니다.

3D 렌더링 컨텍스트란, 3D 변환 렌더링 목적상 공통 조상에 뿌리를 둔 요소 집합으로서, 공통 3차원 좌표계를 공유하는 것으로 간주됩니다. 3D 렌더링 컨텍스트 내 요소들의 앞뒤 렌더링 순서는 해당 3차원 공간에서의 z-위치에 따라 달라지며, 만약 요소의 3D 변환이 교차하게 되면 교차하여 렌더링됩니다.

각 요소의 3차원 공간 내 위치는 해당 요소에서 3D 렌더링 컨텍스트를 설정하는 요소까지 변환 행렬을 누적하여 결정됩니다.

요소는 다음과 같이 3D 렌더링 컨텍스트를 설정하거나 참여합니다:

일부 CSS 속성 값은 "그룹화"를 강제하는 것으로 간주됩니다. 이는 해당 요소와 자손이 다른 요소와 합성되기 전에 그룹으로 렌더링되어야 함을 의미합니다. 대표적으로 opacity, filter, 클리핑에 영향을 주는 속성 등이 있으며, 관련 속성 값은 그룹화 속성 값에 나열되어 있습니다. 따라서 transform-style:preserve-3d가 적용된 요소에 이들 속성이 사용되면 사용 값이 flat으로 변경되어 3D 렌더링 컨텍스트를 생성하거나 확장하지 않도록 합니다.

3D 렌더링 컨텍스트에서는 요소의 렌더링 및 정렬이 다음과 같이 이루어집니다:

  1. 3D 렌더링 컨텍스트를 설정한 요소와, 해당 컨텍스트에 참여하는 다른 3D 변환 요소는 각자의 평면에 렌더링됩니다. 이 평면에는 요소의 배경, 테두리, 기타 박스 장식, 콘텐츠, 자손 요소가 포함되며, 자체 평면을 가진 자손(및 그 자손)은 제외됩니다. 이 렌더링은 CSS 2.1, Appendix E, Section E.2 페인팅 순서에 따라 수행됩니다.

  2. 이 평면 집합 간의 교차는 Newell 알고리즘에 따라 이루어지며, 각 평면은 누적된 3D 변환 행렬로 변환됩니다. 동일 평면의 3D 변환 요소는 페인팅 순서대로 렌더링됩니다.

2D 변환된 요소를 별도 평면으로 분리하지 않아도 되는지?

참고: 이전 명세에서는 3D 렌더링 컨텍스트를 설정하는 요소의 배경, 테두리, 기타 박스 장식을 전체 3D 장면 뒤에 렌더링한다고 정의했으나, #6238에서 변경되었습니다. 향후 3D 렌더링 컨텍스트 정의가 변경되면 다시 고려될 수 있습니다.

transform에 음수 z-성분이 있는 요소는 설정 요소의 콘텐츠 및 변환되지 않은 자손 뒤에 렌더링되며, 3D 변환 요소는 콘텐츠 및 변환되지 않은 요소와 겹칠 수 있습니다.

참고: 3D 렌더링 컨텍스트 내의 3D 변환 요소들은 모두 깊이 정렬 및 교차가 가능하므로, 실질적으로 서로 형제처럼 렌더링됩니다. transform-style: preserve-3d의 효과는 3D 렌더링 컨텍스트 내 모든 3D 변환 요소를 설정 요소로 끌어올리되, 각 요소는 누적된 3D 변환 행렬에 따라 렌더링하는 것과 같습니다.

<style>
div {
  height: 150px;
  width: 150px;
}
.scene {
  background-color: rgba(0, 0, 0, 0.3);
  border: 1px solid black;
  perspective: 500px;
}
.container {
  transform-style: preserve-3d;
}
.container > div {
  position: absolute;
  left: 0;
}
.container > :first-child {
  transform: rotateY(45deg);
  background-color: orange;
  top: 10px;
  height: 135px;
}
.container > :last-child {
  transform: translateZ(40px);
  background-color: rgba(0, 0, 255, 0.6);
  top: 50px;
  height: 100px;
}
</style>

<div class="scene">
  <div class="container">
    Lorem ipsum dolor sit amet, consectetaur adipisicing elit…
    <div></div>
    <div></div>
  </div>
</div>

이 예시는 3D 렌더링 컨텍스트 내에서 요소들이 어떻게 교차할 수 있는지를 보여줍니다. 컨테이너 요소는 자신과 두 자식 요소에 대해 3D 렌더링 컨텍스트를 설정하며, scene 요소는 해당 3D 렌더링 컨텍스트에 원근을 추가합니다. 자식 요소들은 서로 교차하고, 오렌지 색 요소는 컨테이너와도 교차합니다.

교차하는 형제 요소.
<style>
div {
  height: 150px;
  width: 150px;
}
.container {
  perspective: 500px;
  border: 1px solid black;
}
.transformed {
  transform: rotateY(50deg);
  background-color: blue;
}
.child {
  transform-origin: top left;
  transform: rotateX(40deg);
  background-color: lime;
}
</style>

<div class="container">
  <div class="transformed">
    <div class="child"></div>
  </div>
</div>

이 예시는 중첩된 3D 변환이 어떻게 렌더링되는지 보여줍니다. 파란 div는 이전 예시와 같이 변환되며, 부모 요소의 perspective에 의해 렌더링이 영향을 받습니다. 라임(lime) 요소도 X축 기준 3D 변환(상단 기준 transform-origin)되어 있지만, 라임 요소는 부모의 평면에 렌더링되므로 동일한 3D 렌더링 컨텍스트에 속하지 않습니다. 따라서 라임 요소는 단순히 짧아 보일 뿐 파란 요소에서 "튀어나오는" 효과는 없습니다.

중첩 3D 변환, 평면화(flattening)

4.1.3. 변환 요소 계층 구조

기본적으로 변환 요소3D 렌더링 컨텍스트를 생성하지 않으며 내용이 평면화(flattened)되어 렌더링됩니다. 하지만, 공통 3차원 공간을 공유하는 변환 객체 계층을 만드는 것이 유용하므로, transform-style 속성에 preserve-3d 값을 지정하여 이 평면화 동작을 무시할 수 있습니다. 이 설정을 하면 변환 요소의 자손들이 동일한 3D 렌더링 컨텍스트를 공유할 수 있습니다. 그런 요소의 비-3D 변환 자손은 위 C 단계에서 요소의 평면에 렌더링되지만, 동일 3D 렌더링 컨텍스트의 3D 변환 요소는 자신의 평면으로 "튀어나옵니다".

<style>
div {
  height: 150px;
  width: 150px;
}
.container {
  perspective: 500px;
  border: 1px solid black;
}
.transformed {
  transform-style: preserve-3d;
  transform: rotateY(50deg);
  background-color: blue;
}
.child {
  transform-origin: top left;
  transform: rotateX(40deg);
  background-color: lime;
}
</style>

이 예시는 이전 예시와 동일하지만, 파란 요소에 transform-style: preserve-3d가 추가된 것입니다. 파란 요소는 이제 컨테이너의 3D 렌더링 컨텍스트를 확장합니다. 이제 파란 요소와 라임 요소 모두 공통 3차원 공간을 공유하므로, 라임 요소는 컨테이너의 perspective에 영향을 받아 부모에서 기울어진 채로 "튀어나와" 렌더링됩니다.

중첩 3D 변환, preserve-3d

4.1.4. 누적 3D 변환 행렬 계산

3D 렌더링 컨텍스트에서 요소를 렌더링하는 데 사용되는 최종 transform 값은 다음과 같이 누적 3D 변환 행렬을 누적하여 계산됩니다:

  1. transform을 단위 행렬로 둡니다.

  2. current element를 변환된 요소로 둡니다.

  3. parent element를 변환된 요소의 부모 요소로 둡니다.

  4. current element가 변환된 요소의 3D 렌더링 컨텍스트에 속하는 요소일 때 동안:

    1. current elementtransform의 값이 none이 아니면, current element변환 행렬transform에 전치 곱(pre-multiply)합니다.

    2. current elementparent element로부터의 오프셋(스크롤 오프셋 포함)을 나타내는 이동 행렬을 계산하고, 그 행렬을 transform에 전치 곱합니다.

    3. parent elementperspective의 값이 none이 아니면, parent element원근 행렬transform에 전치 곱합니다.

    4. current elementparent element로 둡니다.

    5. parent elementcurrent element의 부모로 둡니다.

참고: 여기 설명된 대로, 누적 3D 변환 행렬은 변환된 요소 및 해당 조상 체인(3D 렌더링 컨텍스트를 설정하는 요소까지 포함)의 시각적 포맷팅 모델에 의해 생성된 오프셋(스크롤 오프셋 포함)을 고려합니다.

4.1.5. 뒷면(Backface) 표시 여부

3차원 변환을 사용하면 요소가 뒤집혀서 뒷면이 보이도록 변환할 수 있습니다. 3D 변환된 요소는 양쪽에 동일한 콘텐츠를 표시하므로, 뒷면은 앞면의 거울상처럼 보입니다(요소가 유리판에 투영된 것처럼). 일반적으로 뒷면이 사용자 쪽을 향할 때에도 요소는 표시됩니다. 그러나 backface-visibility 속성을 사용하면 요소의 뒷면이 사용자 쪽을 향할 때 요소를 보이지 않게 할 수 있습니다. 이 동작은 "실시간"입니다. 만약 backface-visibility: hidden이 설정된 요소가 애니메이션되어 앞면과 뒷면이 번갈아 보인다면, 앞면이 사용자 쪽을 향할 때만 요소가 보입니다.

요소의 뒷면 표시 여부는 누적 3D 변환 행렬을 기준으로 고려되며, 이는 3D 렌더링 컨텍스트를 설정하는 요소의 부모에 대해 상대적입니다.

참고: 이 속성은 두 요소를 등 뒤로 배치하여 카드처럼 만드는 경우에 유용합니다. 이 속성이 없으면 애니메이션 중에 앞면과 뒷면 요소가 위치를 바꿀 수 있습니다. 또 다른 예로 6개의 요소로 박스를 만들 때, 박스의 내부 면만 보고 싶을 때 사용할 수 있습니다.

이 예시는 클릭 시 뒤집히는 "카드" 요소를 만드는 방법을 보여줍니다. #card의 "transform-style: preserve-3d"는 뒤집힐 때 평면화(flattening)를 방지하기 위해 필요합니다.

<style>
.body { perspective: 500px; }
#card {
  position: relative;
  height: 300px; width: 200px;
  transition: transform 1s;
  transform-style: preserve-3d;
}
#card.flipped {
  transform: rotateY(180deg);
}
.face {
  position: absolute;
  top: 0; left: 0;
  width: 100%; height: 100%;
  background-color: silver;
  border-radius: 40px;
  backface-visibility: hidden;
}
.back {
  transform: rotateY(180deg);
}
</style>
<div id="card" onclick="this.classList.toggle('flipped')">
  <div class="front face">Front</div>
  <div class="back face">Back</div>
</div>

backface-visibility가 변환되지 않거나 2D 변환된 요소에 미치는 영향은? 별도 평면으로 분리되고 교차하게 되는가?

4.2. 원근 변환된 박스 처리

제공된 행렬을 사용하여 요소를 정확히 변환하는 방법을 명확하게 규정하려는 첫 시도입니다. 완벽하지 않을 수 있으며, 구현자 피드백을 권장합니다. #912 참고.

누적 3D 변환 행렬perspective 속성뿐 아니라 transform 속성 값에 포함된 perspective() 변환 함수에도 영향을 받습니다.

누적 3D 변환 행렬은 4×4 행렬이며, 변환할 객체는 2차원 박스입니다. 박스의 각 꼭짓점(a, b)을 변환하려면 먼저 행렬을 (a, b, 0, 1)에 적용하면, (x, y, z, w)의 4차원 점이 됩니다. 이 점을 아래와 같이 3차원 점(x′, y′, z′)으로 변환합니다:

w > 0인 경우, (x′, y′, z′) = (x/w, y/w, z/w)입니다.

w = 0인 경우, (x′, y′, z′) = (xn, yn, zn)입니다. n은 구현에 따라 선택되는 값으로, 가능하면 x′ 또는 y′가 뷰포트 크기보다 훨씬 크도록 해야 합니다. 예를 들어, (5px, 22px, 0px, 0)은 (5000px, 22000px, 0px)으로 변환될 수 있으며, n = 1000입니다. 하지만 (0.1px, 0.05px, 0px, 0)에는 이 값이 너무 작을 수 있습니다. 이 명세는 n의 값을 정확히 정의하지 않습니다. 개념적으로 (x′, y′, z′)는 (x, y, z) 방향으로 무한히 멀리 있는 점입니다.

변환된 박스의 네 꼭짓점 모두 w < 0이면, 박스는 렌더링되지 않습니다.

변환된 박스의 한 꼭짓점부터 세 꼭짓점이 w < 0이면, 해당 부분을 잘라내어 다각형(폴리곤)으로 대체해야 합니다. 일반적으로 꼭짓점이 3~5개인 폴리곤이 되며, 그 중 정확히 두 꼭짓점은 w = 0이고 나머지는 w > 0입니다. 이 꼭짓점들은 위 규칙을 사용하여 3차원 점으로 변환됩니다. 개념적으로 w < 0인 점은 "사용자 뒤"에 있으므로 보이지 않아야 합니다.

.transformed {
  height: 100px;
  width: 100px;
  background: lime;
  transform: perspective(50px) translateZ(100px);
}

박스의 모든 꼭짓점의 z 좌표가 perspective보다 크므로, 박스는 사용자 뒤에 있고 표시되지 않습니다. 수식적으로, (x, y)는 먼저 (x, y, 0, 1)이 되고, 그 다음 (x, y, 100, 1)로 이동됩니다. perspective 적용 후에는 (x, y, 100, −1)이 되어 w가 음수이므로 표시되지 않습니다. w < 0을 별도로 처리하지 않는 구현은 이 점을 (−x, −y, −100)으로 잘못 표시할 수 있습니다. −1로 나누어 박스를 반전시키는 것입니다.

.transformed {
  height: 100px;
  width: 100px;
  background: radial-gradient(yellow, blue);
  transform: perspective(50px) translateZ(50px);
}

이 경우 박스가 위쪽으로 이동하여 사용자가 바라보는 위치에 놓이게 됩니다. 즉, 박스를 점점 더 가까이 가져와 시야 전체를 채우는 것과 같습니다. 기본 transform-origin이 박스의 중앙(노란색)이므로 화면은 노란색으로 채워집니다.

수식적으로, (x, y)는 먼저 (x, y, 0, 1)이 되고, 그 다음 (x, y, 50, 1)로 이동됩니다. perspective 적용 후에는 (x, y, 50, 0)이 됩니다. 중심 기준으로 왼쪽 위 꼭짓점은 (−50, −50)이므로, (−50, −50, 50, 0)이 됩니다. 이 값은 매우 멀리 왼쪽 위로 변환되며, 예를 들어 (−5000, −5000, 5000) 등이 될 수 있습니다. 다른 꼭짓점도 마찬가지로 멀리 이동합니다. radial-gradient는 박스 전체에 늘어나므로, 스크롤 없이 보이는 부분은 가운데 픽셀의 색상(노란색)이 됩니다. 하지만 박스는 실제로 무한하지 않으므로 사용자가 가장자리(파란색 부분)까지 스크롤할 수 있습니다.

.transformed {
  height: 50px;
  width: 50px;
  background: lime;
  border: 25px solid blue;
  transform-origin: left;
  transform: perspective(50px) rotateY(-45deg);
}

박스가 사용자 쪽으로 회전되고, 왼쪽 가장자리는 고정된 상태에서 오른쪽 가장자리가 가까워집니다. 오른쪽 가장자리는 z = 70.7px에 위치하며, 이는 perspective 50px보다 가깝습니다. 따라서 오른쪽 가장자리는 "사용자 뒤"로 사라지고, 보이는 부분은 오른쪽으로 무한히 늘어납니다.

수식적으로, 박스의 오른쪽 위 꼭짓점은 transform-origin 기준으로 원래 (100, −50)입니다. 첫 번째로 (100, −50, 0, 1)로 확장되고, 지정된 변환을 적용하면 대략 (70.71, −50, 70.71, −0.4142)가 됩니다. w = −0.4142 < 0이므로 w < 0인 부분을 잘라내야 합니다. 이 결과로 새로운 오른쪽 위 꼭짓점은 (50, −50, 50, 0)이 되고, 이는 (5000, −5000, 5000)처럼 같은 방향으로 멀리 변환됩니다. 아래 오른쪽 꼭짓점도 마찬가지로 멀리 이동합니다. 결과적으로 박스는 화면 오른쪽을 넘어서까지 늘어납니다.

박스는 여전히 유한하므로 사용자가 전체를 보려면 스크롤할 수 있습니다. 그러나 오른쪽 부분은 잘려서 아무리 스크롤해도 원래 박스의 오른쪽 30px 정도는 보이지 않습니다. 파란색 테두리는 25px로, 왼쪽, 위, 아래에는 보이지만 오른쪽에는 보이지 않습니다.

한 꼭짓점 또는 세 꼭짓점이 w < 0인 경우에도 기본 처리 방법은 동일합니다. 이 경우 w < 0 부분을 잘라내면 사각형 대신 삼각형이나 오각형이 됩니다.

5. 개별 변환 속성: translate, scale, rotate 속성

translate, rotate, scale 속성을 사용하면 작성자는 간단한 변환을 각각 독립적으로 지정할 수 있습니다. 이는 일반적인 사용자 인터페이스 사용 방식에 맞게 동작하며, transform에서 translate(), rotate(), scale()의 순서를 기억하지 않고도 각각 독립적으로 화면 좌표계에서 동작하도록 합니다.

이름: translate
값: none | <length-percentage> [ <length-percentage> <length>? ]?
초기값: none
적용 대상: 변환 가능한 요소
상속: no
백분율: 참조 박스의 너비(첫 번째 값) 또는 높이(두 번째 값)를 기준으로 함
계산된 값: 키워드 none 또는 계산된 <length-percentage> 값 쌍과 절대 길이
정식 순서: 문법에 따름
애니메이션 타입: 계산된 값 기준, 단 none은 아래 참고

translate 속성은 1~3개의 값을 받으며, 각각 한 축에 대한 이동을 지정합니다(X, Y, Z 순서). 두 번째 또는 세 번째 값이 없으면 0px으로 기본 처리됩니다.

세 번째 값이 생략되거나 0이면 2D 이동을 지정하는 것이며, translate() 함수와 동일합니다. 그렇지 않으면 3D 이동을 지정하며, translate3d() 함수와 동일합니다.

참고: resolved value로서의 translate 속성 값은 계산된 값이며, getComputedStyle() 결과에 백분율 값이 포함됩니다.

이름: rotate
값: none | <angle> | [ x | y | z | <number>{3} ] && <angle>
초기값: none
적용 대상: 변환 가능한 요소
상속: no
백분율: 해당 없음
계산된 값: 키워드 none 또는 <angle> + 축(3개의 <number> 리스트)
정식 순서: 문법에 따름
애니메이션 타입: SLERP 방식, 단 none은 아래 참고

rotate 속성은 요소를 회전시키는 각도를 받고, 필요에 따라 회전 축도 지정할 수 있습니다.

회전 축은 x, y, 또는 z 키워드로 지정할 수 있습니다. 이는 해당 축을 중심으로 회전하며, rotateX(), rotateY(), rotateZ() 변환 함수와 동일합니다. 또는, x, y, z 성분을 가진 원점 중심 벡터(세 개의 숫자)를 명시적으로 지정하여 rotate3d() 함수와 동일하게 할 수 있습니다.

행동상의 차이는 없습니다. 단순한 <angle>만 지정한 회전과 z축을 중심으로 지정한 회전(키워드 z 사용, 또는 벡터의 앞 두 성분이 0이고 세 번째 성분이 양수인 경우) 모두 rotate() 함수와 동일한 2D 회전입니다. 예를 들어, rotate: 30deg, rotate: z 30deg, rotate: 0 0 1 30deg는 모두 동일합니다.

이름: scale
값: none | [ <number> | <percentage> ]{1,3}
초기값: none
적용 대상: 변환 가능한 요소
상속: no
백분율: 해당 없음
계산된 값: 키워드 none 또는 3개의 <number> 리스트
정식 순서: 문법에 따름
애니메이션 타입: 계산된 값 기준, 단 none은 아래 참고

scale 속성은 1~3개의 값을 받고, 각각 한 축의 스케일을 지정합니다(X, Y, Z 순서).

Y 값이 없으면, X 값과 동일하게 기본 처리됩니다.

Z 값이 없으면, 1로 기본 처리됩니다.

세 번째 값이 생략, 1 또는 100%이면, 2D 스케일이며, scale() 함수와 동일합니다. 그렇지 않으면, 3D 스케일이며, scale3d() 함수와 동일합니다.

세 번째 값이 생략된 것과 1 또는 100%인 것은 동작상 차이가 없습니다.

<percentage><number>와 동일하며, 예를 들어 scale: 100%scale: 1과 같습니다. 지정값 및 계산값 직렬화 시 숫자가 사용됩니다.


세 속성 모두 (기본값도) none 값을 사용할 수 있으며, 이는 변환을 전혀 적용하지 않습니다. 특히, 이 값은 스태킹 컨텍스트모든 자손의 포함 블록 생성을 유발하지 않습니다. 그 외 모든 값 (예: translate: 0px처럼 “단위” 변환 포함) 은 변환의 일반 규칙에 따라 스태킹 컨텍스트와 모든 자손의 포함 블록을 생성합니다.

translate, rotate, scale이 애니메이션 또는 트랜지션 중일 때, from 값 또는 to 값(둘 중 하나만)이 none이면, none 값은 해당 단위(identity) 값(translate: 0px, rotate: 0deg, scale: 1)으로 대체됩니다.

5.1. 직렬화

이 속성들은 두 가지 뚜렷한 동작 모드(변환 없음 vs 변환 있음)를 가지므로, 직렬화 시 이를 고려해야 합니다:

translate에 대해

변환 값이 지정된 경우, 속성은 1~3개의 값으로 직렬화되어야 합니다. (관례적으로 두 번째와 세 번째 값이 0px일 때(기본값), 또는 세 번째 값만 0px일 때, 직렬화 시 해당 0px 값은 생략해야 합니다).

원래 none이 지정되었을 때에만 none 키워드로 직렬화해야 합니다. (단위 변환은 포함되지 않으므로, 0px으로 직렬화해야 합니다.)

rotate에 대해

z축(즉, 2D) 회전이 지정된 경우, 속성은 <angle>만으로 직렬화되어야 합니다.

기타 회전이 지정된 경우, 축이 지정된 상태로 직렬화되어야 하며, 축이 x나 y축에 평행할 경우 적절한 키워드로 직렬화되어야 합니다.

원래 none이 지정되었을 때에만 none 키워드로 직렬화해야 합니다. (단위 변환은 포함되지 않으므로, 0deg로 직렬화해야 합니다.)

scale에 대해

스케일이 지정된 경우, 속성은 1~3개의 값으로만 직렬화되어야 합니다. 관례적으로 세 번째 값이 1(기본값)일 때, 직렬화 시 생략해야 합니다. 세 번째 값이 생략되고 두 번째 값이 첫 번째 값과 같을 때(기본값), 직렬화 시 두 번째 값도 생략합니다.

원래 none이 지정되었을 때에만 none 키워드로 직렬화해야 합니다. (단위 변환은 포함되지 않으므로, 1로 직렬화해야 합니다.)

6. 현재 변환 행렬

변환 행렬 계산은 다음과 같이 수정됩니다:

변환 행렬은 transform, transform-origin, translate, rotate, scale, offset 속성으로부터 다음과 같이 계산됩니다:

  1. 단위 행렬로 시작합니다.

  2. transform-origin의 계산된 X, Y, Z 값만큼 이동(translate)합니다.

  3. translate의 계산된 X, Y, Z 값만큼 이동합니다.

  4. <angle>만큼 지정된 축을 기준으로 회전합니다(rotate).

  5. scale의 계산된 X, Y, Z 값만큼 스케일합니다.

  6. offset에 지정된 변환만큼 이동 및 회전합니다.

  7. transform에 있는 각 변환 함수를 왼쪽에서 오른쪽 순서로 곱합니다.

  8. transform-origin의 계산된 X, Y, Z 값의 음수만큼 이동합니다.

7. transform-style 속성

이름: transform-style
값: flat | preserve-3d
초기값: flat
적용 대상: 변환 가능한 요소
상속: no
백분율: N/A
계산된 값: 지정된 키워드
정식 순서: 문법에 따름
애니메이션 타입: 불연속(discrete)
사용 값: 그룹화 속성이 있으면 flat, 없으면 지정된 키워드

transform-style의 계산된 값이 preserve-3d변환 가능한 요소는 스태킹 컨텍스트와 모든 자손의 포함 블록을 설정합니다. 사용 값이 preserve-3d이면 3D 렌더링 컨텍스트도 설정 또는 확장합니다.

7.1. 그룹화 속성 값

아래 CSS 속성 값들은 UA가 자손 요소들을 먼저 평면화하여 렌더링해야 하므로, 해당 요소의 preserve-3d의 사용 값을 flat으로 강제합니다.

8. perspective 속성

이름: perspective
값: none | <length [0,∞]>
초기값: none
적용 대상: 변환 가능한 요소
상속: no
백분율: N/A
계산된 값: 키워드 none 또는 절대 길이
정식 순서: 문법에 따름
애니메이션 타입: 계산된 값 기준
<length [0,∞]>

투영의 중심까지의 거리입니다.

투영이 중심까지의 거리인지 검증 필요.

<length> 값이 너무 작으면 렌더링 결과가 비정상적이거나 변환 계산의 수치 정확도가 떨어질 수 있으므로, 1px 미만 값은 렌더링 목적상 1px로 처리해야 합니다. (이 클램핑은 내부 값에는 영향을 주지 않으므로, 스타일시트에 perspective: 0;이 있으면 직렬화 결과는 0으로 남습니다.)

none

원근 변환이 적용되지 않습니다. 수학적으로는 <length> 값이 무한대인 것과 유사합니다. 모든 객체가 평면에 평평하게 보입니다.

이 속성에 none 이외의 값이 사용되면 스태킹 컨텍스트가 생성됩니다. 또한 모든 자손의 포함 블록도 생성됩니다. 이는 transform 속성과 동일합니다.

perspective에서 스태킹 컨텍스트나 포함 블록을 반드시 생성할 필요는 없지만, 웹 호환성 때문에 변경할 수 없을 수도 있습니다.

perspectiveperspective-origin 속성 값은 위에서 설명한 대로 원근 행렬 계산에 사용됩니다.

9. perspective-origin 속성

perspective-origin 속성은 perspective 속성의 기준점을 설정합니다. 이는 해당 요소의 자식들을 볼 때, 시청자가 바라보는 X, Y 위치를 효과적으로 지정합니다.

이름: perspective-origin
값: <position>
초기값: 50% 50%
적용 대상: 변환 가능한 요소
상속: no
백분율: reference box의 크기를 기준으로 함
계산된 값: background-position 참고
정식 순서: 문법에 따름
애니메이션 타입: 계산된 값 기준

perspectiveperspective-origin 속성 값은 위에서 설명한 대로 perspective matrix 계산에 사용됩니다.

perspective-origin의 값은 reference box의 왼쪽 위 모서리로부터의 오프셋을 나타냅니다.

<percentage>

수평 방향의 백분율은 reference box의 너비를 기준으로 합니다. 수직 방향의 백분율은 reference box의 높이를 기준으로 합니다. 수평 및 수직 오프셋 값은 reference box의 왼쪽 위 모서리로부터의 오프셋입니다.

<length>

길이 값은 고정된 길이 오프셋을 제공합니다. 수평 및 수직 오프셋은 reference box의 왼쪽 위 모서리로부터의 오프셋입니다.

top

한 개 또는 두 개의 값이 주어졌을 때 수직 위치는 0%로 계산되며, 그렇지 않으면 다음 오프셋의 기준점을 상단으로 지정합니다.

right

한 개 또는 두 개의 값이 주어졌을 때 수평 위치는 100%로 계산되며, 그렇지 않으면 다음 오프셋의 기준점을 오른쪽으로 지정합니다.

bottom

한 개 또는 두 개의 값이 주어졌을 때 수직 위치는 100%로 계산되며, 그렇지 않으면 다음 오프셋의 기준점을 하단으로 지정합니다.

left

한 개 또는 두 개의 값이 주어졌을 때 수평 위치는 0%로 계산되며, 그렇지 않으면 다음 오프셋의 기준점을 왼쪽으로 지정합니다.

center

수평 위치가 별도로 지정되지 않은 경우 50%(left 50%)로 계산되며, 수직 위치가 지정된 경우 50%(top 50%)로 계산됩니다.

perspective-origin 속성은 height와 같은 resolved value 특례 속성입니다. [CSSOM]

10. backface-visibility 속성

이름: backface-visibility
값: visible | hidden
초기값: visible
적용 대상: 변환 가능한 요소
상속: no
백분율: N/A
계산된 값: 지정된 키워드
정식 순서: 문법에 따름
애니메이션 타입: 불연속(discrete)

backface-visibility: hidden이 적용된 요소의 표시 여부는 다음과 같이 결정됩니다:

  1. 요소의 누적 3D 변환 행렬을 계산합니다.

  2. 행렬의 3행 3열 성분이 음수이면, 요소를 숨겨야 하며 그렇지 않으면 표시됩니다.

Backface-visibility는 m33만으로 판단할 수 없음. #917 참고.

참고: 이 정의의 논리는 다음과 같습니다. 요소를 두께가 극히 얇은 x–y 평면의 직사각형으로 가정합니다. 변환되지 않은 요소의 앞면 좌표는 (x, y, ε), 뒷면은 (x, y, −ε)입니다(ε는 매우 작은 값). 변환 후 앞면이 뒷면보다 사용자에게 더 가까운지(더 높은 z값) 판단하고자 합니다. 앞면의 z 좌표는 m13x + m23y + m33ε + m43이고, 뒷면은 m13x + m23y − m33ε + m43입니다. 첫 번째 값이 두 번째 값보다 크려면 m33 > 0 이어야 합니다.(0이면 앞면과 뒷면이 동일 거리, 대략 90도 회전 등으로 보이지 않음. 실제로 사라지는 것이므로 신경 쓸 필요 없음)

11. SVG 및 3D 변환 함수

이 명세는 3차원 변환 함수가 다음 컨테이너 요소에 적용되는 것을 명시적으로 요구합니다: a, g, svg, 모든 그래픽 요소, 모든 그래픽 참조 요소 및 SVG foreignObject 요소.

3차원 변환 함수 및 perspective, perspective-origin, transform-style, backface-visibility 속성은 다음 요소에는 사용할 수 없습니다: clipPath, linearGradient, radialGradientpattern. 변환 리스트에 3차원 변환 함수가 포함되어 있으면, 전체 변환 리스트는 무시되어야 합니다. 앞서 명시된 모든 속성 값도 무시되어야 합니다. 이러한 요소에 포함된 변환 가능한 요소는 3차원 변환 함수를 가질 수 있습니다. clipPath, mask, pattern 요소는 UA가 자손 요소를 먼저 평면화하여 렌더링해야 하므로, transform-style: preserve-3d의 동작을 덮어씁니다.

vector-effect 속성이 non-scaling-stroke로 설정되어 있고 객체가 3D 렌더링 컨텍스트 내에 있으면 해당 속성은 스트로크에 아무런 영향을 주지 않습니다.

SVG 내 3D 변환 함수의 문법을 2D 함수처럼 공식적으로 기술 필요.

12. 변환 함수

transform 속성의 값은 <transform-function> 리스트입니다. 허용되는 변환 함수 집합은 아래와 같습니다. 이 명세에서 <angle>이 사용되는 모든 곳에서, 0과 같은 <number>도 허용되며 이는 0도의 각도와 동일하게 처리됩니다. 수평 이동에서의 백분율은 reference box의 너비를 기준으로 하며, 수직 이동에서는 reference box의 높이를 기준으로 합니다. scale 함수의 백분율은 숫자와 동일하며, 지정값 직렬화 시 숫자로 직렬화됩니다. 예를 들어, scale3d(50%, 100%, 150%)scale3d(0.5, 1, 1.5)로 직렬화됩니다.

12.1. 2D 변환 함수

[css-transforms-1]에서 정의된 scale 함수는 이제 백분율을 지원합니다.

scale() = scale( [ <number> | <percentage> ]#{1,2} )
scaleX() = scaleX( [ <number> | <percentage> ] )
scaleY() = scaleY( [ <number> | <percentage> ] )

css-transforms-1에서 정의된 것과 같지만, 위에서 설명한 것처럼 백분율도 허용합니다.

12.2. 3D 변환 함수

아래 3d 변환 함수에서 <zero>0deg와 동일하게 동작합니다. ("단위 없는 0" 각도는 레거시 호환성 때문에 유지됨.)

matrix3d() = matrix3d( <number>#{16} )

16개의 값으로 구성된 4x4 동차 행렬(컬럼 우선 순서)로 3D 변환을 지정합니다.

translate3d() = translate3d( <length-percentage> , <length-percentage> , <length> )

첫 번째, 두 번째, 세 번째 매개변수 tx, ty, tz로 이루어진 벡터 [tx,ty,tz] 만큼 3D 이동을 지정합니다.

translateZ() = translateZ( <length> )

[0,0,tz] 벡터로 지정된 Z 방향으로 3D 이동을 지정합니다.

scale3d() = scale3d( [ <number> | <percentage> ]#{3} )

세 매개변수로 지정된 [sx,sy,sz] 스케일 벡터만큼 3D 스케일 동작을 지정합니다.

scaleZ() = scaleZ( [ <number> | <percentage> ] )

[1,1,sz] 스케일 벡터로 지정된 3D 스케일 동작을 지정합니다. sz는 해당 매개변수 값입니다.

rotate3d() = rotate3d( <number> , <number> , <number> , [ <angle> | <zero> ] )

첫 세 매개변수로 지정된 [x,y,z] 방향 벡터를 기준으로 마지막 매개변수의 각도만큼 3D 회전을 지정합니다. [0,0,0]처럼 정규화할 수 없는 방향 벡터는 회전이 적용되지 않습니다.

참고: 벡터 끝에서 원점을 바라보면 시계 방향 회전입니다.

rotateX() = rotateX( [ <angle> | <zero> ] )

rotate3d(1, 0, 0, <angle>)과 동일합니다.

rotateY() = rotateY( [ <angle> | <zero> ] )

rotate3d(0, 1, 0, <angle>)과 동일합니다.

rotateZ() = rotateZ( [ <angle> | <zero> ] )

rotate3d(0, 0, 1, <angle>)과 동일하며, 이는 2D 변환 rotate(<angle>)과 동일한 3D 변환입니다.

perspective() = perspective( <length [0,∞]> | none )

원근 투영 행렬을 지정합니다. 이 행렬은 Z 값에 따라 X, Y 방향으로 점을 스케일링하며, Z가 양수이면 원점에서 멀어지고, 음수이면 원점 쪽으로 가까워집니다. z=0 평면의 점은 변화가 없습니다. 매개변수는 z=0 평면에서 시청자까지의 거리를 나타냅니다. 값이 작을수록 원근 효과가 더 강해집니다. 예를 들어, 1000px은 약간의 축소 효과, 200px은 극단적 원근 효과를 줍니다.

깊이 값이 1px 미만이면, 렌더링, resolved value 계산, transform의 결과, 보간 결과 모두에서 1px로 처리해야 합니다.

참고: 위 규칙은 perspective() 함수를 행렬로 변환해야 할 때의 경우를 포함하려고 만든 것입니다.

12.3. 변환 함수 프리미티브와 파생 함수

일부 변환 함수는 더 일반적인 변환 함수로 표현될 수 있습니다. 이러한 변환 함수는 파생 변환 함수(derived transform functions)라 하며, 일반적인 변환 함수는 프리미티브 변환 함수(primitive transform functions)라 합니다. 3차원 프리미티브와 그 파생 변환 함수는 다음과 같습니다:

translate3d()
<translateX()>, <translateY()>, translateZ(), <translate()>에 해당합니다.
scale3d()
<scaleX()>, <scaleY()>, scaleZ(), <scale()>에 해당합니다.
rotate3d()
<rotate()>, rotateX(), rotateY(), rotateZ()에 해당합니다.

2차원 프리미티브와 3차원 프리미티브를 모두 가지는 파생 변환 함수의 경우, 사용되는 프리미티브는 문맥(context)에 따라 결정됩니다. 자세한 내용은 프리미티브 및 파생 변환 함수의 보간을 참조하세요.

13. 행렬 보간

두 행렬 간의 보간 시, 각 행렬은 대응하는 이동(translation), 회전(rotation), 스케일(scale), 왜곡(skew) 및 (3D 행렬의 경우) 원근(perspective) 값으로 분해됩니다. 분해된 행렬의 각 대응 컴포넌트들은 수치적으로 보간되고, 마지막 단계에서 다시 행렬로 합성(recompose)됩니다.

13.1. 3D 행렬의 보간

13.1.1. 3D 행렬 분해

아래 의사코드는 "Graphics Gems II, edited by Jim Arvo"의 "unmatrix" 방법을 기반으로 하지만, Gimbal Lock 문제를 피하기 위해 오일러 각 대신 쿼터니언(Quaternion)을 사용하도록 수정되었습니다.

다음의 의사코드는 4x4 동차 행렬(homogeneous matrix)에 적용됩니다:

Input:  matrix      ; a 4x4 matrix
Output: translation ; a 3 component vector
        scale       ; a 3 component vector
        skew        ; skew factors XY,XZ,YZ represented as a 3 component vector
        perspective ; a 4 component vector
        quaternion  ; a 4 component vector
Returns false if the matrix cannot be decomposed, true if it can


// Normalize the matrix.
if (matrix[3][3] == 0)
    return false

for (i = 0; i < 4; i++)
    for (j = 0; j < 4; j++)
        matrix[i][j] /= matrix[3][3]

// perspectiveMatrix is used to solve for perspective, but it also provides
// an easy way to test for singularity of the upper 3x3 component.
perspectiveMatrix = matrix

for (i = 0; i < 3; i++)
    perspectiveMatrix[i][3] = 0

perspectiveMatrix[3][3] = 1

if (determinant(perspectiveMatrix) == 0)
    return false

// First, isolate perspective.
if (matrix[0][3] != 0 || matrix[1][3] != 0 || matrix[2][3] != 0)
    // rightHandSide is the right hand side of the equation.
    rightHandSide[0] = matrix[0][3]
    rightHandSide[1] = matrix[1][3]
    rightHandSide[2] = matrix[2][3]
    rightHandSide[3] = matrix[3][3]

    // Solve the equation by inverting perspectiveMatrix and multiplying
    // rightHandSide by the inverse.
    inversePerspectiveMatrix = inverse(perspectiveMatrix)
    transposedInversePerspectiveMatrix = transposeMatrix4(inversePerspectiveMatrix)
    perspective = multVecMatrix(rightHandSide, transposedInversePerspectiveMatrix)
else
    // No perspective.
    perspective[0] = perspective[1] = perspective[2] = 0
    perspective[3] = 1

// Next take care of translation
for (i = 0; i < 3; i++)
    translate[i] = matrix[3][i]

// Now get scale and shear. 'row' is a 3 element array of 3 component vectors
for (i = 0; i < 3; i++)
    row[i][0] = matrix[i][0]
    row[i][1] = matrix[i][1]
    row[i][2] = matrix[i][2]

// Compute X scale factor and normalize first row.
scale[0] = length(row[0])
row[0] = normalize(row[0])

// Compute XY shear factor and make 2nd row orthogonal to 1st.
skew[0] = dot(row[0], row[1])
row[1] = combine(row[1], row[0], 1.0, -skew[0])

// Now, compute Y scale and normalize 2nd row.
scale[1] = length(row[1])
row[1] = normalize(row[1])
skew[0] /= scale[1];

// Compute XZ and YZ shears, orthogonalize 3rd row
skew[1] = dot(row[0], row[2])
row[2] = combine(row[2], row[0], 1.0, -skew[1])
skew[2] = dot(row[1], row[2])
row[2] = combine(row[2], row[1], 1.0, -skew[2])

// Next, get Z scale and normalize 3rd row.
scale[2] = length(row[2])
row[2] = normalize(row[2])
skew[1] /= scale[2]
skew[2] /= scale[2]

// At this point, the matrix (in rows) is orthonormal.
// Check for a coordinate system flip.  If the determinant
// is -1, then negate the matrix and the scaling factors.
pdum3 = cross(row[1], row[2])
if (dot(row[0], pdum3) < 0)
    for (i = 0; i < 3; i++)
        scale[i] *= -1;
        row[i][0] *= -1
        row[i][1] *= -1
        row[i][2] *= -1

// Now, get the rotations out
quaternion[0] = 0.5 * sqrt(max(1 + row[0][0] - row[1][1] - row[2][2], 0))
quaternion[1] = 0.5 * sqrt(max(1 - row[0][0] + row[1][1] - row[2][2], 0))
quaternion[2] = 0.5 * sqrt(max(1 - row[0][0] - row[1][1] + row[2][2], 0))
quaternion[3] = 0.5 * sqrt(max(1 + row[0][0] + row[1][1] + row[2][2], 0))

if (row[2][1] > row[1][2])
    quaternion[0] = -quaternion[0]
if (row[0][2] > row[2][0])
    quaternion[1] = -quaternion[1]
if (row[1][0] > row[0][1])
    quaternion[2] = -quaternion[2]

return true

13.1.2. 분해된 3D 행렬 값의 보간

분해된 translation, scale, skew, perspective 값의 각 컴포넌트는 출발 행렬과 도착 행렬에서 각각 선형적으로 보간(linear interpolation)됩니다.

참고: 예를 들어, 출발 행렬의 translate[0]와 도착 행렬의 translate[0]는 수치적으로 보간되고, 그 결과는 애니메이션 요소의 이동 값으로 사용됩니다.

분해된 출발 행렬의 쿼터니언(quaternion)은 분해된 도착 행렬의 쿼터니언과 구면 선형 보간법(Slerp)으로 보간되며, 아래의 의사코드처럼 처리합니다:

Input:  quaternionA   ; a 4 component vector
        quaternionB   ; a 4 component vector
        t             ; interpolation parameter with 0 <= t <= 1
Output: quaternionDst ; a 4 component vector


product = dot(quaternionA, quaternionB)

// Clamp product to -1.0 <= product <= 1.0
product = min(product, 1.0)
product = max(product, -1.0)

if (abs(product) == 1.0)
   quaternionDst = quaternionA
   return

theta = acos(product)
w = sin(t * theta) / sqrt(1 - product * product)

for (i = 0; i < 4; i++)
  quaternionA[i] *= cos(t * theta) - product * w
  quaternionB[i] *= w
  quaternionDst[i] = quaternionA[i] + quaternionB[i]

return

13.1.3. 3D 행렬로 재조합

보간 후 결과 값들은 요소의 사용자 공간(user space)을 변환하는 데 사용됩니다. 한 가지 방법은 이 값들을 4x4 행렬로 다시 합성(recompose)하는 것으로, 아래 의사코드와 같이 처리할 수 있습니다:

Input:  translation ; a 3 component vector
        scale       ; a 3 component vector
        skew        ; skew factors XY,XZ,YZ represented as a 3 component vector
        perspective ; a 4 component vector
        quaternion  ; a 4 component vector
Output: matrix      ; a 4x4 matrix

Supporting functions (matrix is a 4x4 matrix):
  matrix  multiply(matrix a, matrix b)   returns the 4x4 matrix product of a * b

// apply perspective
for (i = 0; i < 4; i++)
  matrix[i][3] = perspective[i]

// apply translation
for (i = 0; i < 4; i++)
  for (j = 0; j < 3; j++)
    matrix[3][i] += translation[j] * matrix[j][i]

// apply rotation
x = quaternion[0]
y = quaternion[1]
z = quaternion[2]
w = quaternion[3]

// Construct a composite rotation matrix from the quaternion values
// rotationMatrix is a identity 4x4 matrix initially
rotationMatrix[0][0] = 1 - 2 * (y * y + z * z)
rotationMatrix[0][1] = 2 * (x * y - z * w)
rotationMatrix[0][2] = 2 * (x * z + y * w)
rotationMatrix[1][0] = 2 * (x * y + z * w)
rotationMatrix[1][1] = 1 - 2 * (x * x + z * z)
rotationMatrix[1][2] = 2 * (y * z - x * w)
rotationMatrix[2][0] = 2 * (x * z - y * w)
rotationMatrix[2][1] = 2 * (y * z + x * w)
rotationMatrix[2][2] = 1 - 2 * (x * x + y * y)

matrix = multiply(matrix, rotationMatrix)

// apply skew
// temp is a identity 4x4 matrix initially
if (skew[2])
    temp[2][1] = skew[2]
    matrix = multiply(matrix, temp)

if (skew[1])
    temp[2][1] = 0
    temp[2][0] = skew[1]
    matrix = multiply(matrix, temp)

if (skew[0])
    temp[2][0] = 0
    temp[1][0] = skew[0]
    matrix = multiply(matrix, temp)

// apply scale
for (i = 0; i < 3; i++)
  for (j = 0; j < 4; j++)
    matrix[i][j] *= scale[i]

return

14. 프리미티브 및 파생 변환 함수의 보간

이름과 인자 개수가 동일한 두 변환 함수는 변환 없이 수치적으로 보간됩니다. 계산된 값은 동일한 변환 함수 타입과 동일한 인자 개수를 가집니다. <matrix()>, <matrix3d()>, <perspective()>에는 특별 규칙이 적용됩니다.

<matrix()>, matrix3d(), perspective() 변환 함수는 먼저 4x4 행렬로 변환되고, 이후 행렬 보간 섹션에 따라 보간됩니다.

프리미티브 rotate3d()의 보간에서는, 변환 함수의 방향 벡터가 먼저 정규화됩니다. 정규화된 벡터가 같지 않고 두 회전 각도가 모두 0이 아니면, 변환 함수는 먼저 4x4 행렬로 변환된 후 행렬 보간 섹션에 따라 보간됩니다. 그렇지 않으면 회전 각도만 수치적으로 보간되고, 0이 아닌 각도의 회전 벡터가 사용되거나(둘 다 0이면 (0, 0, 1) 사용) 사용됩니다.

translate(0)translate(100px) 두 변환 함수는 동일한 타입, 동일한 인자 개수를 가지므로 수치적으로 보간 가능합니다. translateX(100px)은 타입이 다르고 translate(100px, 0)은 인자 개수가 다르므로, 이 변환 함수들은 변환 없이 바로 보간될 수 없습니다.

프리미티브가 동일한 서로 다른 타입의 변환 함수, 또는 동일 타입이지만 인자 개수가 다른 변환 함수도 보간이 가능합니다. 두 변환 함수 모두 먼저 공통 프리미티브로 변환된 후 수치적으로 보간됩니다. 계산된 값은 보간된 인자를 가진 프리미티브가 됩니다.

다음 예시는 div 박스에 마우스를 올릴 때 translateX(100px)에서 translateY(100px)로 3초간 전환되는 트랜지션을 설명합니다. 두 변환 함수 모두 동일한 프리미티브 translate()에서 파생되므로 보간이 가능합니다.

div {
  transform: translateX(100px);
}

div:hover {
  transform: translateY(100px);
  transition: transform 3s;
}

트랜지션 동안 두 변환 함수 모두 공통 프리미티브로 변환됩니다. translateX(100px)translate(100px, 0)으로, translateY(100px)translate(0, 100px)으로 변환됩니다. 이후 두 변환 함수는 수치적으로 보간될 수 있습니다.

두 변환 함수가 2차원 공간의 프리미티브를 공유한다면, 두 변환 함수 모두 2차원 프리미티브로 변환됩니다. 하나 또는 두 변환 함수가 3차원 변환 함수라면, 공통 3차원 프리미티브가 사용됩니다.

이 예시에서는 2차원 변환 함수가 3차원 변환 함수로 애니메이션됩니다. 공통 프리미티브는 translate3d()입니다.

div {
  transform: translateX(100px);
}

div:hover {
  transform: translateZ(100px);
  transition: transform 3s;
}

먼저 translateX(100px)translate3d(100px, 0, 0)으로, translateZ(100px)translate3d(0, 0, 100px)으로 변환됩니다. 그런 다음 변환된 두 함수는 수치적으로 보간됩니다.

15. 변환 리스트의 덧셈 및 누적

두 변환 리스트 VaVb의 덧셈은 리스트 연결로 정의되며, VresultVb추가되어 Va와 같습니다.
두 변환 리스트의 누적 VaVb는 보간과 동일한 절차를 따르며, 변환 함수 일치, 단위 변환 함수로 리스트 패딩, none단위 변환 함수로 변환, 필요 시 두 인자를 행렬로 변환(자세한 것은 CSS Transforms 1 § 11 변환 보간 참고). 단, 개별 파라미터를 보간하는 대신, 덧셈을 사용해 결합합니다—단, 단위 변환 함수에서 값이 1인 파라미터(scale 파라미터, 행렬 요소 m11, m22, m33, m44 등)는 1 기반 값의 누적 규칙에 따라 결합:

Vresult = Va + Vb - 1

위 정의는 누적의 의도—VbVa에서 델타로 작동하며 아래와 같은 애니메이션이 가능함을—보존합니다:
div.animate(
  { transform: ['scale(1)', 'scale(2)'] },
  {
    duration: 1000,
    easing: 'ease',
  }
);

이를 아래처럼 확장하면 기대한 대로 동작합니다:

div.animate(
  { transform: ['scale(1)', 'scale(2)'] },
  {
    duration: 1000,
    easing: 'ease',
    iterations: 5,
    iterationComposite: 'accumulate',
  }
);

15.1. 덧셈의 중립 원소

일부 애니메이션에서는 덧셈의 중립 원소가 필요합니다. 변환 함수에서 중립 원소란 0 또는 0 리스트입니다. 예시로 translate(0), translate3d(0, 0, 0), translateX(0), translateY(0), translateZ(0), scale(0), scaleX(0), scaleY(0), scaleZ(0), rotate(0), rotate3d(vx, vy, vz, 0) (여기서 v는 문맥 의존 벡터), rotateX(0), rotateY(0), rotateZ(0), skew(0, 0), skewX(0), skewY(0), matrix(0, 0, 0, 0, 0, 0), matrix3d(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), perspective(none) 등이 있습니다.

참고: <matrix()>, matrix3d(), perspective()의 중립 원소로의 애니메이션은 불연속 애니메이션으로 처리됩니다(§ 13 행렬 보간 참고).

16. 변환 함수의 수학적 설명

수학적으로 모든 변환 함수는 다음 형식의 4x4 변환 행렬로 표현할 수 있습니다:

$$\begin{bmatrix} m11 & m21 & m31 & m41 \\ m12 & m22 & m32 & m42 \\ m13 & m23 & m33 & m43 \\ m14 & m24 & m34 & m44 \end{bmatrix}$$

행렬에서 1 이동 단위는 요소의 로컬 좌표계에서 1픽셀에 해당합니다.

17. SVG transform 속성

이 명세는 새로운 표현 속성 transform-origin, perspective, perspective-origin, transform-style, backface-visibility도 도입합니다.

새로 도입된 표현 속성의 값은 SVG 데이터 타입 [SVG11]의 구문 규칙을 따라 파싱됩니다.

18. SVG 애니메이션

18.1. animateset 요소

도입된 표현 속성 perspective, perspective-origin, transform-style, backface-visibility는 애니메이션이 가능합니다. transform-stylebackface-visibility는 비가산(non-additive) 속성입니다.

19. 추가 이슈

https://lists.w3.org/Archives/Public/www-style/2015Mar/0371.html에 따라, WG는 변환을 통합 "scale"로 분해하는 공식을 추가하기로 결정했습니다 (명세에서는 이미 scaleX/Y/Z로 분해하는 방법을 정의함). 이는 SVG의 non-scaling stroke 명세 등에서 사용할 수 있습니다. 공식은 여기 정의되어 있습니다.

20. 보안 및 개인정보 보호 고려 사항

이 명세는 새로운 보안 또는 개인정보 보호 고려 사항을 도입하지 않습니다.

변경사항

최근 변경사항

2020년 3월 3일 WD 이후 주요 변경사항:

적합성

문서 규약

적합성 요구사항은 설명적 명제와 RFC 2119 용어의 조합으로 표현됩니다. “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, “OPTIONAL” 등의 키워드는 RFC 2119에서 설명된 대로 해석됩니다. 다만 가독성을 위해 이 명세에서는 모두 대문자로 표기하지 않습니다.

명세의 모든 텍스트는 명시적으로 비규범적임, 예시, 주석임을 표시한 섹션을 제외하고 규범적입니다. [RFC2119]

이 명세의 예시는 “예를 들어”라는 문구로 시작하거나, class="example"로 구분되어 있습니다:

이것은 정보성 예시입니다.

정보성 주석은 “참고”라는 단어로 시작하며 class="note"로 구분됩니다:

참고, 이것은 정보성 주석입니다.

권고문은 규범적 섹션이며, <strong class="advisement">로 스타일링되어 특별히 주의를 환기합니다: UA는 반드시 접근 가능한 대안을 제공해야 합니다.

적합성 클래스

이 명세에 대한 적합성은 세 가지 적합성 클래스에 대해 정의됩니다:

스타일 시트
CSS 스타일 시트
렌더러
UA: 스타일 시트의 의미를 해석하고, 이를 사용하는 문서를 렌더링함
작성 도구
UA: 스타일 시트를 작성하는 도구

스타일 시트가 이 명세에 적합하려면, 이 모듈에서 정의한 구문을 사용하는 모든 선언문이 CSS 일반 문법 및 각 기능별 문법에 따라 유효해야 합니다.

렌더러가 이 명세에 적합하려면, 스타일 시트를 적절한 명세에 따라 해석하는 것 외에도, 이 명세에서 정의한 모든 기능을 지원하며 이를 올바르게 파싱하고 문서를 그에 따라 렌더링해야 합니다. 단, 디바이스의 한계로 인해 UA가 문서를 올바르게 렌더링할 수 없는 경우, UA가 비적합하다고 간주하지 않습니다. (예: UA가 흑백 모니터에서 색상 렌더링을 요구받을 필요는 없음)

작성 도구가 이 명세에 적합하려면, 작성한 스타일 시트가 CSS 일반 문법 및 각 모듈의 개별 기능 문법에 따라 구문적으로 올바르며, 이 모듈에서 설명한 스타일 시트의 모든 적합성 요구사항을 충족해야 합니다.

부분 구현

작성자가 전방 호환 파싱 규칙을 활용해 폴백 값을 지정할 수 있도록, CSS 렌더러는 반드시 지원 가능한 수준의 지원이 없는 모든 at-규칙, 속성, 속성 값, 키워드 및 기타 구문 구조를 무효(적절하게 무시)로 취급해야 합니다. 특히 UA는 지원되지 않는 일부 값만 무시하고, 지원되는 값만 처리하는 방식으로 다중 값 속성 선언을 부분적으로 처리해서는 안 됩니다: 어떤 값이 무효(지원되지 않는 값은 반드시 무효임)로 간주되면 CSS는 전체 선언을 무시해야 합니다.

불안정 및 독점 기능의 구현

향후 안정적인 CSS 기능과 충돌을 피하기 위해, CSSWG는 베스트 프랙티스를 따를 것과 불안정 기능 및 독점 확장 구현 시 지침을 권장합니다.

비실험적 구현

명세가 Candidate Recommendation 단계에 도달하면, 비실험적 구현이 가능하며, 구현자는 명세에 따라 올바르게 구현되었음을 입증할 수 있는 CR 레벨 기능에 대해 접두어 없는 구현을 출시하는 것이 바람직합니다.

CSS의 구현 간 상호 운용성을 확립하고 유지하기 위해, CSS 워킹 그룹은 비실험적 CSS 렌더러가 CSS 기능의 접두어 없는 구현을 출시하기 전에 W3C에 구현 보고서(필요한 경우 해당 테스트케이스도 함께)를 제출할 것을 요청합니다. W3C에 제출된 테스트케이스는 CSS 워킹 그룹의 검토 및 수정 대상이 됩니다.

테스트케이스 및 구현 보고서 제출에 관한 추가 정보는 CSS 워킹 그룹 웹사이트 https://www.w3.org/Style/CSS/Test/ 에서 확인할 수 있습니다. 문의는 public-css-testsuite@w3.org 메일링 리스트로 보내세요.

색인

이 명세에서 정의된 용어

참고 명세에서 정의된 용어

참고문헌

규범적 참고문헌

[COMPOSITING-1]
Rik Cabanier; Nikos Andronikos. Compositing and Blending Level 1. 2015년 1월 13일. CR. URL: https://www.w3.org/TR/compositing-1/
[CSS-BACKGROUNDS-3]
Bert Bos; Elika Etemad; Brad Kemper. CSS Backgrounds and Borders Module Level 3. 2021년 7월 26일. CR. URL: https://www.w3.org/TR/css-backgrounds-3/
[CSS-CASCADE-5]
Elika Etemad; Miriam Suzanne; Tab Atkins Jr.. CSS Cascading and Inheritance Level 5. 2021년 10월 15일. WD. URL: https://www.w3.org/TR/css-cascade-5/
[CSS-COLOR-4]
Tab Atkins Jr.; Chris Lilley. CSS Color Module Level 4. 2021년 6월 1일. WD. URL: https://www.w3.org/TR/css-color-4/
[CSS-CONTAIN-1]
Tab Atkins Jr.; Florian Rivoal. CSS Containment Module Level 1. 2020년 12월 22일. REC. URL: https://www.w3.org/TR/css-contain-1/
[CSS-MASKING-1]
Dirk Schulze; Brian Birtles; Tab Atkins Jr.. CSS Masking Module Level 1. 2021년 8월 5일. CR. URL: https://www.w3.org/TR/css-masking-1/
[CSS-OVERFLOW-3]
David Baron; Elika Etemad; Florian Rivoal. CSS Overflow Module Level 3. 2020년 6월 3일. WD. URL: https://www.w3.org/TR/css-overflow-3/
[CSS-TRANSFORMS-1]
Simon Fraser; et al. CSS Transforms Module Level 1. 2019년 2월 14일. CR. URL: https://www.w3.org/TR/css-transforms-1/
[CSS-VALUES-3]
Tab Atkins Jr.; Elika Etemad. CSS Values and Units Module Level 3. 2019년 6월 6일. CR. URL: https://www.w3.org/TR/css-values-3/
[CSS-VALUES-4]
Tab Atkins Jr.; Elika Etemad. CSS Values and Units Module Level 4. 2021년 10월 16일. WD. URL: https://www.w3.org/TR/css-values-4/
[CSS21]
Bert Bos; et al. Cascading Style Sheets Level 2 Revision 1 (CSS 2.1) Specification. 2011년 6월 7일. REC. URL: https://www.w3.org/TR/CSS21/
[CSSOM]
Daniel Glazman; Emilio Cobos Álvarez. CSS Object Model (CSSOM). 2021년 8월 26일. WD. URL: https://www.w3.org/TR/cssom-1/
[FILTER-EFFECTS-1]
Dirk Schulze; Dean Jackson. Filter Effects Module Level 1. 2018년 12월 18일. WD. URL: https://www.w3.org/TR/filter-effects-1/
[HTML]
Anne van Kesteren; et al. HTML Standard. Living Standard. URL: https://html.spec.whatwg.org/multipage/
[INFRA]
Anne van Kesteren; Domenic Denicola. Infra Standard. Living Standard. URL: https://infra.spec.whatwg.org/
[MOTION-1]
Dirk Schulze; et al. Motion Path Module Level 1. 2018년 12월 18일. WD. URL: https://www.w3.org/TR/motion-1/
[RFC2119]
S. Bradner. Key words for use in RFCs to Indicate Requirement Levels. 1997년 3월. Best Current Practice. URL: https://datatracker.ietf.org/doc/html/rfc2119
[SVG11]
Erik Dahlström; et al. Scalable Vector Graphics (SVG) 1.1 (Second Edition). 2011년 8월 16일. REC. URL: https://www.w3.org/TR/SVG11/
[SVG2]
Amelia Bellamy-Royds; et al. Scalable Vector Graphics (SVG) 2. 2018년 10월 4일. CR. URL: https://www.w3.org/TR/SVG2/

참고용 참고문헌

[CSS-CONTAIN-2]
Tab Atkins Jr.; Florian Rivoal; Vladimir Levin. CSS Containment Module Level 2. 2020년 12월 16일. WD. URL: https://www.w3.org/TR/css-contain-2/

속성 색인

이름 초기값 적용 대상 상속 % 비율 애니메이션 타입 정식 순서 계산된 값 사용 값
backface-visibility visible | hidden visible transformable elements no N/A 불연속(discrete) 문법에 따름 지정된 키워드
perspective none | <length [0,∞]> none transformable elements no N/A 계산된 값 기준 문법에 따름 키워드 none 또는 절대 길이
perspective-origin <position> 50% 50% transformable elements no reference box 크기 기준 계산된 값 기준 문법에 따름 background-position 참고
rotate none | <angle> | [ x | y | z | <number>{3} ] && <angle> none transformable elements no n/a SLERP 방식, 단 none은 아래 참고 문법에 따름 키워드 none 또는 축(3개의 <number> 리스트)이 포함된 <angle>
scale none | [ <number> | <percentage> ]{1,3} none transformable elements no n/a 계산된 값 기준, 단 none은 아래 참고 문법에 따름 키워드 none 또는 3개의 <number> 리스트
transform-style flat | preserve-3d flat transformable elements no N/A 불연속(discrete) 문법에 따름 지정된 키워드 그룹화 속성이 있으면 flat, 없으면 지정된 키워드
translate none | <length-percentage> [ <length-percentage> <length>? ]? none transformable elements no 첫 번째 값은 reference box 너비, 두 번째 값은 높이 기준 계산된 값 기준, 단 none은 아래 참고 문법에 따름 키워드 none 또는 계산된 <length-percentage> 쌍과 절대 길이

이슈 색인

이 텍스트를 CSS Transforms 1의 내용에 추가하도록 수정 필요.
중첩된 3d 변환 요소의 렌더링 방식(수식 등 포함) 설명 필요
이 예시는 앞서 나온 텍스트와 연결되지 않음.
2D 변환된 요소를 별도 평면으로 분리하지 않아도 되는지?
backface-visibility가 변환되지 않거나 2D 변환된 요소에 미치는 영향은? 별도 평면으로 분리되고 교차하게 되는가?
제공된 행렬을 사용하여 요소를 정확히 변환하는 방법을 명확하게 규정하려는 첫 시도입니다. 완벽하지 않을 수 있으며, 구현자 피드백을 권장합니다. #912.
투영이 중심까지의 거리인지 검증 필요.
perspective에서 스태킹 컨텍스트나 포함 블록을 반드시 생성할 필요는 없지만, 웹 호환성 때문에 변경할 수 없을 수도 있습니다.
backface-visibility는 m33만으로 판단할 수 없음. #917 참고.
SVG 내 3D 변환 함수의 문법을 2D 함수처럼 공식적으로 기술 필요.
https://lists.w3.org/Archives/Public/www-style/2015Mar/0371.html에 따라, WG는 변환을 통합 "scale"로 분해하는 공식을 추가하기로 결정했습니다 (명세에서는 이미 scaleX/Y/Z로 분해하는 방법을 정의함), 이는 SVG의 non-scaling stroke 명세 등에서 사용할 수 있습니다. 공식은 여기 정의되어 있습니다.