CSS 변환 모듈 레벨 1

W3C 후보 권고안,

이 버전:
https://www.w3.org/TR/2019/CR-css-transforms-1-20190214/
최신 공개 버전:
https://www.w3.org/TR/css-transforms-1/
편집자 초안:
https://drafts.csswg.org/css-transforms/
이전 버전:
테스트 스위트:
http://test.csswg.org/suites/css-transforms-1_dev/nightly-unstable/
편집자:
(Apple Inc)
(Apple Inc)
(Apple Inc)
(Adobe Inc)
이전 편집자:
(Apple Inc)
(Apple Inc)
(Mozilla)
이 명세 수정 제안:
GitHub 편집자
이슈 추적:
GitHub 이슈

요약

CSS 변환은 CSS로 스타일링된 요소를 2차원 공간에서 변환할 수 있게 합니다. 이 명세는 CSS 2D 변환SVG 변환 명세의 통합입니다.

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

문서 상태

이 섹션은 이 문서가 게시될 당시의 상태를 설명합니다. 다른 문서가 이 문서를 대체할 수 있습니다. 현재 W3C 출판물 목록 및 이 기술 보고서의 최신 개정판은 W3C 기술 보고서 인덱스 https://www.w3.org/TR/에서 확인할 수 있습니다.

이 문서는 CSS 워킹 그룹에 의해 후보 권고안으로 작성되었습니다. 이 문서는 W3C 권고안이 될 예정입니다. 이 문서는 폭넓은 검토 기회를 보장하기 위해 최소 까지 후보 권고안으로 유지됩니다.

이 명세의 논의는 GitHub 이슈에서 하는 것이 권장됩니다. 이슈를 등록할 때 제목에 “css-transforms”를 포함해 주시기 바랍니다. 예시: “[css-transforms] …코멘트 요약…”. 모든 이슈와 코멘트는 아카이브되며, 히스토리 아카이브도 있습니다.

초기 구현 보고서가 제공됩니다.

후보 권고안으로 출판되었다고 해서 W3C 회원의 승인을 의미하지는 않습니다. 이 문서는 초안이며 언제든지 업데이트, 대체 또는 폐기될 수 있습니다. 진행 중인 작업 외에는 인용에 적합하지 않습니다.

이 문서는 W3C 특허 정책에 따라 운영되는 그룹에서 작성되었습니다. W3C는 해당 그룹 산출물과 관련된 특허 공개 목록을 유지합니다; 해당 페이지에는 특허 공개 방법도 안내되어 있습니다. 어떤 개인이 필수 청구항(Essential Claim(s))을 포함한다고 믿는 특허에 대해 실제로 알게 되면, W3C 특허 정책 6절에 따라 정보를 공개해야 합니다.

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

마지막 초안 이후의 변경 사항은 변경 사항 섹션을 참고하세요.

1. 소개

이 섹션은 규범적이지 않습니다.

CSS 시각적 포맷팅 모델은 각 요소가 배치되는 좌표계를 설명합니다. 이 좌표 공간에서 위치와 크기는 픽셀 단위로 표현된다고 볼 수 있으며, 원점에서 시작하여 오른쪽과 아래쪽으로 양의 값이 진행됩니다.

이 좌표 공간은 transform 속성으로 변경할 수 있습니다. transform을 사용하면 요소를 이동, 회전, 확대/축소할 수 있습니다.

1.1. 모듈 상호작용

이 모듈은 해당 속성이 적용된 요소의 시각적 렌더링에 영향을 주는 CSS 속성 집합을 정의합니다. 이러한 효과는 요소가 시각적 포맷팅 모델 [CSS2]에 따라 크기와 위치가 결정된 이후에 적용됩니다. 이 속성의 일부 값은 포함 블록을 생성하거나, 스태킹 컨텍스트를 생성할 수 있습니다.

Transform은 fixed 값이 지정된 background-attachment 속성을 가진 요소의 배경 렌더링에 영향을 줍니다. 이는 [CSS3BG]에서 정의되어 있습니다.

Transform은 getClientRects()getBoundingClientRect()와 같은 Element 인터페이스 확장에서 반환되는 클라이언트 사각형에도 영향을 줍니다. 이는 [CSSOM-VIEW]에서 정의되어 있습니다.

Transform은 스크롤 가능한 오버플로우 영역의 계산에도 영향을 줍니다. 자세한 내용은 [CSS-OVERFLOW-3]를 참조하세요.

1.2. CSS 값

이 명세는 CSS 속성 정의 관례[CSS2]에서 따릅니다. 이 명세에서 정의되지 않은 값 타입은 CSS Values & Units [CSS-VALUES-3]에서 정의됩니다. 다른 CSS 모듈이 이러한 값 타입의 정의를 확장할 수 있습니다.

각 속성 정의에 명시된 속성 전용 값 외에도, 이 명세에서 정의된 모든 속성은 CSS-wide 키워드도 속성 값으로 사용할 수 있습니다. 가독성을 위해 이를 반복적으로 명시하지 않았습니다.

2. 용어 정의

이 명세에서 사용되는 용어는 본 섹션에서 정의된 의미를 갖습니다.

변환 가능한 요소

변환 가능한 요소란 다음 범주에 속하는 요소를 말합니다:

변환된 요소

transform 속성의 계산값이 none이 아닌 요소.

사용자 좌표계
로컬 좌표계

일반적으로, 좌표계는 현재 캔버스에서 위치와 거리를 정의합니다. 현재 로컬 좌표계(사용자 좌표계)는 현재 활성화된 좌표계이며, 좌표와 길이가 어떻게 위치하고 계산되는지를 결정합니다. 현재 사용자 좌표계의 원점은 기준 박스(transform-box 속성으로 지정) 왼쪽 상단에 위치합니다. 백분율 값은 이 기준 박스의 크기를 기준으로 합니다. 한 단위는 1 CSS 픽셀과 같습니다.

변환 행렬

한 좌표계에서 다른 좌표계로의 수학적 매핑을 정의하는 행렬입니다. transformtransform-origin 속성 값에서 계산됩니다(아래 참조).

현재 변환 행렬 (CTM)

로컬 좌표계에서 뷰포트 좌표계로의 매핑을 정의하는 행렬입니다.

2D 행렬

3x2 변환 행렬 또는 다음 항목들이 0이고 m33, m441인 4x4 행렬: m31, m32, m13, m23, m43, m14, m24, m34.

항등 변환 함수

변환 함수 중 항등 4x4 행렬과 동일한 함수(자세한 내용은 변환 함수의 수학적 설명 참조). 예시: translate(0), translateX(0), translateY(0), scale(1), scaleX(1), scaleY(1), rotate(0), skew(0, 0), skewX(0), skewY(0), matrix(1, 0, 0, 1, 0, 0).

포스트 곱셈
포스트 곱셈됨

용어 A를 용어 B로 포스트 곱셈한다는 것은 A · B와 같습니다.

프리 곱셈
프리 곱셈됨

용어 A를 용어 B로 프리 곱셈한다는 것은 B · A와 같습니다.

곱셈

용어 A를 용어 B로 곱셈한다는 것은 A · B와 같습니다.

3. 변환 렌더링 모델

이 섹션은 규범적입니다.

transform 속성에 none 이외의 값을 지정하면 해당 요소에 새로운 로컬 좌표계가 생성됩니다. 요소가 렌더링될 위치에서 이 로컬 좌표계로의 매핑은 요소의 변환 행렬로 주어집니다.

변환 행렬transformtransform-origin 속성에서 다음과 같이 계산됩니다:

  1. 항등 행렬로 시작합니다.

  2. transform-origin의 계산된 X, Y만큼 이동합니다.

  3. transform 속성의 변환 함수 각각을 왼쪽에서 오른쪽으로 곱합니다.

  4. transform-origin의 계산된 X, Y의 부호 반대로 이동합니다.

요소에 transform 속성이 none이 아닌 값으로 지정되어 있습니다.

div {
  transform-origin: 0 0;
  transform: translate(-10px, -20px) scale(2) rotate(45deg);
}

transform-origin 속성이 0 0으로 설정되어 있으므로 생략 가능합니다. 변환 행렬 TM<translate()>, <scale()>, <rotate()> <transform-function>를 포스트 곱셈하여 계산됩니다.

TM = \begin{bmatrix} 1 & 0 & 0 & -10 \\ 0 & 1 & 0 & -20 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix} \cdot \begin{bmatrix} 2 & 0 & 0 & 0 \\ 0 & 2 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix} \cdot \begin{bmatrix} cos(45) & -sin(45) & 0 & 0 \\ sin(45) & cos(45) & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix}

Transform은 변환 가능한 요소에 적용됩니다.

좌표 공간은 두 축(X축과 Y축)으로 이루어진 좌표계이며, X축은 오른쪽으로 수평 증가, Y축은 아래로 수직 증가합니다.

변환은 누적됩니다. 즉, 요소는 부모의 좌표계 내에 자신의 로컬 좌표계를 설정합니다.

요소의 로컬 좌표계에서 plocal (좌표쌍 xlocal, ylocal)을 부모 좌표계로 매핑하려면, 요소의 변환 행렬 TMplocal을 포스트 곱셈합니다. 결과는 부모 로컬 좌표계에서 좌표쌍 xparent, yparent를 갖는 pparent입니다.

\begin{bmatrix} x_{parent} \\ y_{parent} \\ 0 \\ 1 \end{bmatrix} = TM \cdot \begin{bmatrix} x_{local} \\ y_{local} \\ 0 \\ 1 \end{bmatrix}

사용자 관점에서 보면, 요소는 자신의 조상들의 모든 transform 속성뿐 아니라 자신에게 적용된 로컬 변환도 누적합니다. 이러한 변환의 누적은 요소의 현재 변환 행렬(CTM)을 정의합니다.

현재 변환 행렬뷰포트 좌표계에서 시작하여 요소의 변환 행렬까지 모든 변환 행렬을 포스트 곱셈하여 계산됩니다.

이 예제는 SVG 문서에서 여러 중첩된 요소를 포함합니다. 일부 요소는 변환 행렬에 의해 변환됩니다.
<svg xmlns="http://www.w3.org/2000/svg">
  <g transform="translate(-10, 20)">
    <g transform="scale(2)">
      <rect width="200" height="200" transform="rotate(45)"/>
    </g>
  </g>
</svg>

SVG rect 요소의 CTM은 T1, T2, T3를 순서대로 곱한 결과입니다.

CTM = \begin{bmatrix} 1 & 0 & 0 & -10 \\ 0 & 1 & 0 & -20 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix} \cdot \begin{bmatrix} 2 & 0 & 0 & 0 \\ 0 & 2 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix} \cdot \begin{bmatrix} cos(45) & -sin(45) & 0 & 0 \\ sin(45) & cos(45) & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix}

SVG rect 요소의 로컬 좌표계에서 좌표쌍 xlocal, ylocal를 갖는 plocal뷰포트 좌표계로 매핑하려면, 해당 요소의 현재 변환 행렬 CTMplocal을 포스트 곱셈합니다. 결과는 뷰포트 좌표계에서 좌표쌍 xviewport, yviewport를 갖는 pviewport입니다.

\begin{bmatrix} x_{viewport} \\ y_{viewport} \\ 0 \\ 1 \end{bmatrix} = CTM \cdot \begin{bmatrix} x_{local} \\ y_{local} \\ 0 \\ 1 \end{bmatrix}

참고: 변환은 시각적 렌더링에는 영향을 주지만, 오버플로우에 영향을 주는 것 외에는 CSS 레이아웃에는 영향을 주지 않습니다. 변환은 getClientRects()getBoundingClientRect() 등 Element 인터페이스 확장에서 노출되는 클라이언트 사각형을 계산할 때도 고려됩니다. 자세한 내용은 [CSSOM-VIEW]를 참조하세요.

div {
    transform: translate(100px, 100px);
}

이 transform은 요소를 X, Y 방향으로 각각 100픽셀 이동시킵니다.

X, Y 100px 이동
div {
  height: 100px; width: 100px;
  transform-origin: 50px 50px;
  transform: rotate(45deg);
}

transform-origin 속성으로 원점을 X, Y 각각 50픽셀 이동시킵니다. 변환은 원점을 기준으로 요소를 시계 방향으로 45° 회전시킵니다. 모든 변환 함수가 적용된 후, 원점의 이동은 X, Y 각각 -50픽셀만큼 다시 이동됩니다.

원점 이동 예시
div {
  height: 100px; width: 100px;
  transform: translate(80px, 80px) scale(1.5, 1.5) rotate(45deg);
}

시각적으로 div 요소가 왼쪽 아래 방향으로 80px 이동, 150% 확대, 마지막에 45° 회전된 것처럼 보입니다.

<transform-function>은 대응하는 4x4 행렬로 나타낼 수 있습니다. div 박스의 좌표 공간에서 부모 요소의 좌표 공간으로 포인트를 매핑하려면, 이 변환들은 역순으로 곱해집니다:

  1. 회전 행렬을 스케일 행렬에 포스트 곱셈합니다.

  2. 이전 곱셈 결과에 변환(이동) 행렬을 포스트 곱셈하여 누적 변환 행렬을 만듭니다.

  3. 마지막으로, 매핑할 포인트를 누적 변환 행렬에 프리 곱셈합니다.

자세한 내용은 변환 함수 목록을 참고하세요.

상기 변환 시각화

참고: 동일한 렌더링은 아래처럼 변환을 중첩한 요소를 사용해 구현할 수 있습니다:

<div style="transform: translate(80px, 80px)">
    <div style="transform: scale(1.5, 1.5)">
        <div style="transform: rotate(45deg)"></div>
    </div>
</div>

CSS 박스 모델로 레이아웃이 결정되는 요소의 경우, transform 속성은 변환된 요소 주변의 콘텐츠 흐름에는 영향을 주지 않습니다. 하지만 오버플로우 영역의 크기는 변환된 요소를 고려합니다. 이 동작은 요소가 상대 위치로 offset될 때와 유사합니다. 따라서 overflow 속성값이 scroll 또는 auto라면, 변환으로 인해 보이는 영역을 벗어난 콘텐츠를 볼 수 있도록 스크롤바가 표시됩니다. 변환은 오버플로우 영역의 크기를 확장할 수 있으며(축소하지는 않음), 이는 변환 적용 전후 요소의 경계 합집합으로 계산됩니다.

CSS 박스 모델로 레이아웃이 결정되는 요소의 경우, transform 속성이 none이 아닌 값이면 스태킹 컨텍스트가 생성됩니다. 구현체는 부모 스태킹 컨텍스트 내에서 해당 레이어를 z-index: 0인 positioned 요소와 동일한 스태킹 순서로 칠해야 합니다. transform이 적용된 요소가 positioned 요소면 z-index 속성은 [CSS2]에서 설명한 대로 적용되며, 단 auto는 항상 새로운 스태킹 컨텍스트가 생성되므로 0으로 취급합니다.

CSS 박스 모델로 레이아웃이 결정되는 요소의 경우, transform 속성이 none이 아닌 값이면 해당 요소는 모든 자손의 포함 블록을 생성합니다. padding box는 모든 절대 위치 자손, fixed 위치 자손, 자손 fixed 배경에 대한 레이아웃 기준이 됩니다.

모든 자손의 포함 블록이 fixed 위치 자손에 미치는 효과를 보여주기 위해, 아래 코드 두 가지는 동일하게 동작해야 합니다:
<style>
#container {
  width: 300px;
  height: 200px;
  border: 5px dashed black;
  padding: 5px;
  overflow: scroll;
}

#bloat {
  height: 1000px;
}

#child {
  right: 0;
  bottom: 0;
  width: 10%;
  height: 10%;
  background: green;
}
</style>

<div id="container" style="transform:translateX(5px);">
  <div id="bloat"></div>
  <div id="child" style="position:fixed;"></div>
</div>

대조 예시

<div id="container" style="position:relative; z-index:0; left:5px;">
  <div id="bloat"></div>
  <div id="child" style="position:absolute;"></div>
</div>

루트 요소의 fixed 배경은 해당 요소에 지정된 transform에 영향을 받습니다. 나머지 transform이 적용된(즉, 자신 또는 조상에 transform이 적용된) 요소에서는 fixed 값의 background-attachment 속성은 scroll로 처리된 것처럼 동작합니다. background-attachment의 계산값은 영향을 받지 않습니다.

참고: 루트 요소에 변환이 적용되면, 해당 변환은 루트 요소에 지정된 모든 배경을 포함하여 캔버스 전체에 적용됩니다. 루트 요소의 배경 페인팅 영역은 전체 캔버스(무한)이므로, 변환에 따라 원래 화면 밖이었던 배경 일부가 화면에 나타날 수 있습니다. 예를 들어, 루트 요소의 배경이 반복되는 점(dots)이고, scale(0.5) 변환이 적용됐다면, 점의 크기는 절반으로 줄지만 그 개수는 두 배가 되어 여전히 전체 뷰포트를 덮게 됩니다.

4. transform 속성

변환은 transform 속성을 통해 요소가 렌더링되는 좌표계에 적용됩니다. 이 속성은 변환 함수 목록을 포함합니다. 좌표계의 최종 변환 값은 목록의 각 함수를 변환 함수의 수학적 설명에 정의된 대로 해당 행렬로 변환한 뒤, 행렬을 곱해서 얻습니다.

이름: transform
값: none | <transform-list>
초기값: none
적용 대상: 변환 가능한 요소
상속됨: 아니오
백분율: 기준 박스의 크기를 참조함
계산값: 지정한 대로, 단 길이는 절대값으로 변환됨
정준 순서: 문법에 따름
애니메이션 타입: transform list, 보간 규칙 참조

transform의 계산값이 none이 아닌 경우 포함 블록 및 스태킹 컨텍스트에 영향을 줍니다. 자세한 내용은 §3 변환 렌더링 모델을 참조하세요.

<transform-list> = <transform-function>+

4.1. <transform-function> 직렬화

<transform-function>을 직렬화할 때는 각각의 문법에 따라, 문법에 정의된 순서대로 직렬화하며, 가능한 경우 <calc()> 표현식을 피하고, <calc()> 변환도 피하며, 의미가 바뀌지 않는다면 컴포넌트 생략, 토큰을 공백 하나로 연결, 직렬화된 콤마 뒤에는 공백 하나를 추가합니다.

4.2. <transform-list> 계산값의 직렬화

계산값의 <transform-list>는 다음 알고리즘에 따라 하나의 <matrix()> 함수로 직렬화됩니다:

  1. transform을 항등 4x4 행렬로 초기화합니다. transformm11, m22, m33, m44 요소는 1로 설정하고, 나머지 요소는 0으로 설정합니다.

  2. <transform-function><transform-list>에서 모두 transform에 포스트 곱셈합니다.

  3. transform<matrix()> 함수로 직렬화합니다.

5. transform-origin 속성

이름: transform-origin
값:   [ left | center | right | top | bottom | <length-percentage> ]
|
  [ left | center | right | <length-percentage> ]
  [ top | center | bottom | <length-percentage> ] <length>?
|
  [[ center | left | right ] && [ center | top | bottom ]] <length>?
초기값: 50% 50%
적용 대상: 변환 가능한 요소
상속됨: 아니오
백분율: 기준 박스의 크기를 참조함
계산값: background-position 참조
정준 순서: 문법에 따름
애니메이션 타입: 계산값 기준

transform 속성과 transform-origin 속성의 값은 위에서 설명한 대로 변환 행렬을 계산하는 데 사용됩니다.

값이 하나만 지정된 경우 두 번째 값은 center로 간주합니다. 값이 하나 또는 두 개 지정되면 세 번째 값은 0px으로 간주합니다.

값이 두 개 이상 지정되고 키워드가 없거나 사용된 키워드가 center뿐인 경우 첫 번째 값은 수평 위치(또는 오프셋), 두 번째 값은 수직 위치(또는 오프셋)를 나타냅니다. 세 번째 값은 항상 Z 위치(또는 오프셋)를 나타내야 하며, <length> 타입이어야 합니다.

<length-percentage>

수평 오프셋의 백분율 값은 기준 박스의 너비 기준입니다. 수직 오프셋의 백분율 값은 기준 박스의 높이 기준입니다. 수평 및 수직 오프셋 값은 기준 박스의 왼쪽 상단에서의 오프셋을 나타냅니다.

<length>

길이 값은 고정 길이 오프셋입니다. 수평 및 수직 오프셋 값은 기준 박스의 왼쪽 상단에서의 오프셋을 나타냅니다.

top

수직 위치로 0%로 계산됩니다.

right

수평 위치로 100%로 계산됩니다.

bottom

수직 위치로 100%로 계산됩니다.

left

수평 위치로 0%로 계산됩니다.

center

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

CSS 레이아웃 박스가 없는 SVG 요소의 초기 사용값은 사용자 에이전트 스타일 시트에 다음이 포함된 것처럼 0 0입니다:

*:not(svg), *:not(foreignObject) > svg {
    transform-origin: 0 0;
}

transform-origin 속성은 resolved value special case property이며, height와 유사합니다. [CSSOM]

6. 변환 기준 박스: transform-box 속성

이름: transform-box
값: content-box | border-box | fill-box | stroke-box | view-box
초기값: view-box
적용 대상: 변환 가능한 요소
상속됨: 아니오
백분율: 해당 없음
계산값: 지정된 키워드
정준 순서: 문법에 따름
애니메이션 타입: 불연속(discrete)

transformtransform-origin 속성으로 정의되는 모든 변환은 해당 요소의 위치와 크기를 기준으로 하는 기준 박스를 기준으로 상대적으로 적용됩니다. 기준 박스는 다음 중 하나로 지정됩니다:

content-box

콘텐츠 박스를 기준 박스로 사용합니다. 표(table)의 기준 박스는 테이블 래퍼 박스의 테두리 박스(border box)이며, 테이블 박스가 아닙니다.

border-box

테두리 박스를 기준 박스로 사용합니다. 표의 기준 박스도 테이블 래퍼 박스의 테두리 박스입니다.

fill-box

오브젝트 바운딩 박스를 기준 박스로 사용합니다.

stroke-box

스트로크 바운딩 박스를 기준 박스로 사용합니다.

view-box

가장 가까운 SVG 뷰포트를 기준 박스로 사용합니다.

뷰포트를 생성하는 요소에 viewBox 속성이 지정된 경우:

  • 기준 박스는 viewBox 속성으로 설정된 좌표계의 원점에 위치합니다.

  • 기준 박스의 크기는 viewBox 속성의 widthheight 값으로 설정됩니다.

SVG pattern 요소의 경우, 기준 박스는 patternUnits 속성으로 정의됩니다 [SVG2].

SVG linearGradientradialGradient 요소의 경우, 기준 박스는 gradientUnits 속성으로 정의됩니다 [SVG2].

SVG clipPath 요소의 경우, 기준 박스는 clipPathUnits 속성으로 정의됩니다 [CSS-MASKING].

기준 박스는 transform-origin 속성으로 지정한 원점에 추가 오프셋을 더합니다.

CSS 레이아웃 박스가 없는 SVG 요소의 경우, 사용값content-box 대신 fill-box이며, border-box 대신 stroke-box입니다.

CSS 레이아웃 박스가 있는 요소의 경우, 사용값fill-box 대신 content-box이고, stroke-boxview-boxborder-box입니다.

7. SVG transform 속성

7.1. SVG 표시 속성

transform-origin CSS 속성 역시 표시 속성(presentation attribute)이며, 기존 표시 속성 목록을 확장합니다 [SVG2].

SVG 2는 transform, patternTransform, gradientTransform 속성을 표시 속성으로 정의하며, CSS transform 속성으로 표현됩니다 [SVG2].

CSS 캐스케이드 참여 여부는 SVG 명세에서 표시 속성의 특이성(specificity)에 따라 결정됩니다. SVG에 따르면, 사용자 에이전트는 표시 속성에 대해 새 저자 스타일 시트(author style sheet)를 개념적으로 삽입하며, 이는 저자 스타일 시트 집합 중 첫 번째입니다 [SVG2].

이 예제는 transform 스타일 속성과 transform 속성의 조합을 보여줍니다.
<svg xmlns="http://www.w3.org/2000/svg">
  <style>
  .container {
    transform: translate(100px, 100px);
  }
  </style>

  <g class="container" transform="translate(200 200)">
    <rect width="100" height="100" fill="blue" />
  </g>
</svg>
Translated SVG container element.

CSS 캐스케이드 참여로 인해 transform 스타일 속성이 transform 속성보다 우선합니다. 따라서 컨테이너는 200px 대신 수평 및 수직 모두 100px 이동됩니다.

7.2. SVG transform 속성 문법

하위 호환성을 위해 transform, patternTransform, gradientTransform 속성의 문법은 transform CSS 속성의 문법과 다릅니다. 이 속성들에서는 CSS transform 속성에 정의된 추가 <transform-function> 지원이 없습니다. 즉, <translateX()>, <translateY()>, <scaleX()>, <scaleY()>, <skew()>transform, patternTransform, gradientTransform 속성에서 지원되지 않습니다.

다음 목록은 transform, patternTransform, gradientTransform 속성의 값을 BNF로 정의하고, 그 뒤에 참고용 철도 다이어그램이 나옵니다. 사용되는 표기는 다음과 같습니다:

참고: 이 문법은 사용자 에이전트의 구현된 동작을 반영하며, SVG 1.1에서 정의된 문법과 다릅니다.

왼쪽 괄호 (
U+0028 왼쪽 괄호
오른쪽 괄호 )
U+0029 오른쪽 괄호
콤마
U+002C 콤마
wsp
U+000A 줄바꿈, U+000D 캐리지 리턴, U+0009 탭, 또는 U+0020 공백
comma-wsp
(wsp+ comma? wsp*) | (comma wsp*)
translate
"translate" wsp* "(" wsp* number ( comma-wsp? number )? wsp* ")"
scale
"scale" wsp* "(" wsp* number ( comma-wsp? number )? wsp* ")"
rotate
"rotate" wsp* "(" wsp* number ( comma-wsp? number comma-wsp? number )? wsp* ")"
skewX
"skewY" wsp* "(" wsp* number wsp* ")"
skewY
"skewY" wsp* "(" wsp* number wsp* ")"
matrix
"matrix" wsp* "(" wsp*
    number comma-wsp?
    number comma-wsp?
    number comma-wsp?
    number comma-wsp?
    number comma-wsp?
    number wsp* ")"
  
transform
matrix
| translate
| scale
| rotate
| skewX
| skewY
  
transforms
transform
| transform comma-wsp transforms
  
transform-list
wsp* transforms? wsp*

7.3. SVG 변환 함수

위의 문법으로 정의된 transform, patternTransform, gradientTransform 속성의 SVG 변환 함수는 아래와 같이 CSS <transform-function>에 매핑됩니다:

SVG 변환 함수 CSS <transform-function> 추가 설명
translate <translate()> 숫자 값은 CSS <length> 타입으로 해석되며 px 단위가 적용됩니다.
scale <scale()>
rotate <rotate()> 단일 값 버전만 지원. 숫자 값은 CSS <angle> 타입으로 해석되며 deg 단위를 사용합니다.
skewX <skewX()> 숫자 값은 CSS <angle> 타입으로 해석되며 deg 단위를 사용합니다.
skewY <skewY()> 숫자 값은 CSS <angle> 타입으로 해석되며 deg 단위를 사용합니다.
matrix <matrix()>

SVG 변환 함수 rotate에 3개의 값이 있을 경우, 이에 상응하는 CSS <transform-function>으로 매핑할 수 없습니다. 2개의 선택적 숫자 값은 수평 이동 값 cx와 그 다음 수직 이동 값 cy를 나타냅니다. 두 값 모두 CSS <length> 타입으로 해석되며 px 단위를 사용하여 회전의 원점을 정의합니다. 이 동작은 먼저 cx, cy로 이동, 첫 번째 숫자 값으로 <angle> 타입(deg 단위)으로 회전, 그 다음 -cx, -cy로 이동하는 것과 동등합니다.

transform 속성은 CSS 트랜지션의 시작값 또는 끝값이 될 수 있습니다. transform 속성값이 CSS 트랜지션의 시작값 또는 끝값이며 SVG transform list에 3값 rotate 변환 함수가 하나 이상 있으면, 각각의 SVG 변환 함수는 포스트 곱셈되어 결과 행렬을 <matrix()> CSS <transform-function>으로 매핑하고, CSS 트랜지션의 시작/끝값으로 사용해야 합니다.

7.4. 사용자 좌표 공간

pattern 요소에서는 patternTransform 속성 및 transform 속성이 패턴 좌표계에서 추가 변환을 정의합니다. 자세한 내용은 patternUnits 속성을 참고하세요 [SVG2].

linearGradientradialGradient 요소에서는 gradientTransform 속성 및 transform 속성이 그라디언트 좌표계에서 추가 변환을 정의합니다. 자세한 내용은 gradientUnits 속성을 참고하세요 [SVG2].

clipPath 요소에서는 transform 속성 및 transform 속성이 클리핑 경로 좌표 공간에서 추가 변환을 정의합니다. 자세한 내용은 clipPathUnits 속성을 참고하세요 [CSS-MASKING].

그 외의 변환 가능한 요소에서는 transform 속성 및 transform 속성이 부모의 현재 사용자 좌표계에서 변환을 정의합니다. transform 속성의 모든 백분율 값은 해당 요소의 기준 박스를 기준으로 합니다.

다음 예제에서 패턴의 transform-origin 속성은 수평과 수직 모두 50%만큼 원점을 이동시킵니다. transform 속성은 절대 길이로 이동도 지정합니다.

<svg xmlns="http://www.w3.org/2000/svg">
  <style>
  pattern {
    transform: rotate(45deg);
    transform-origin: 50% 50%;
  }
  </style>

  <defs>
  <pattern id="pattern-1">
    <rect id="rect1" width="100" height="100" fill="blue" />
  </pattern>
  </defs>

  <rect width="200" height="200" fill="url(#pattern-1)" />
</svg>

SVG pattern 요소는 바운딩 박스가 없습니다. 참조하는 기준 박스rect 요소의 기준 박스를 사용하여 transform-origin의 상대값을 해결합니다. 따라서 원점은 임시로 100픽셀 이동되어 패턴 요소 콘텐츠의 사용자 공간을 회전시킵니다.

7.5. SVG DOM 인터페이스 (transform 속성)

SVG 명세는 SVG DOM에서 SVG SVGAnimatedTransformList 인터페이스를 정의하여 SVG transform, gradientTransformpatternTransform 속성의 애니메이션 값과 기본 값을 제공하도록 합니다. 하위 호환성을 보장하기 위해 이 API는 사용자 에이전트에서 계속 지원되어야 합니다.

baseVal은 작성자가 SVG transform, patternTransform, gradientTransform 속성의 값을 접근 및 수정할 수 있게 합니다. SVG DOM의 하위 호환성을 제공하기 위해 baseVal은 이 저자 스타일 시트의 값을 반영해야 합니다. baseVal의 SVG DOM 객체를 수정하면 즉시 저자 스타일 시트에 반영되어야 합니다.

animValtransform 속성의 계산 스타일을 나타냅니다. 따라서 적용된 모든 CSS3 트랜지션, CSS3 애니메이션 또는 SVG 애니메이션이 있을 경우 모두 포함됩니다. 계산 스타일 및 animVal의 SVG DOM 객체는 수정할 수 없습니다.

8. SVG 애니메이션

8.1. animateset 요소

이 명세에서는 animate 요소와 set 요소가 <transform-list> 데이터 타입을 애니메이션할 수 있습니다.

애니메이션 효과는 포스트 곱셈(post-multiplied)으로 아래 값에 적용되며, <transform-list> 애니메이션의 특수한 동작 때문에, 아래 값에 더하는 것이 아니라 곱해집니다(아래 참고).

From-to, from-by, by 애니메이션은 SMIL에서 해당 values 애니메이션과 동등하게 정의됩니다. 그러나 to 애니메이션은 가산적(additive) 및 비가산적(non-additive) 동작이 혼합되어 있습니다 [SMIL3].

animate 요소의 to 애니메이션은 아래 값에서 to 속성 값으로 부드럽게 변화하는 특별한 기능을 제공합니다. 그러나 이는 가산적 변환 애니메이션이 포스트 곱셈이어야 한다는 요구와 수학적으로 충돌합니다. 결과적으로 animate 요소의 to 애니메이션 동작은 정의되지 않습니다. 저자는 원하는 변환 애니메이션을 위해 from-to, from-by, by, values 애니메이션을 사용할 것을 권장합니다.

데이터 타입 <transform-list>의 애니메이션에서 calcMode 속성에 "paced" 값을 지정하면 정의되지 않습니다. 지정된 경우 UA는 "linear" 값을 선택할 수 있습니다. 향후 명세에서는 <transform-list>에 대해 pace 애니메이션 방법을 정의할 수 있습니다.

참고: 아래 단락들은 애니메이션 가능한 요소, 속성, 프로퍼티 [SVG11]를 확장합니다.

도입된 표시 속성 transform, patternTransform, gradientTransformtransform-origin은 애니메이션 가능합니다.

이 명세에서 SVG 기본 데이터 타입 <transform-list><transform-function> 목록과 동등합니다. <transform-list>는 애니메이션 및 가산적입니다. 이 데이터 타입은 SVG animate 요소와 SVG set 요소를 사용해 애니메이션할 수 있습니다. SVG 애니메이션은 변환 값 간의 트랜지션 및 애니메이션 절에 설명된 것과 동일한 애니메이션 단계를 따라야 합니다.

애니메이션 가능한 데이터 타입
데이터 타입 가산적? animate set animateColor animateTransform 설명
<transform-list> 아니오 animateTransform 에서 가산적(additive)이란 변환이 기본 변환 집합에 포스트 곱셈된다는 의미입니다.

8.2. 가산의 중립 원소

일부 애니메이션은 가산의 중립 원소가 필요합니다. 변환 함수의 경우 이는 0의 스칼라 또는 스칼라 리스트입니다. 변환 함수의 중립 원소 예시는 translate(0), scale(0), rotate(0), skewX(0), skewY(0) 등이 있습니다.

참고: 이 단락은 [SMIL] 요구사항 및 [SVG11]에서 정의한 확장에 집중합니다. 이 명세는 위에 나열된 함수 이외의 다른 변환 함수에 대한 중립 원소 정의를 제공하지 않습니다.

by 값 vbby 애니메이션을 수행하는 것은, 대상 속성의 도메인(0으로 표기)의 가산 중립 원소와 vb를 values 리스트에 넣고 additive="sum"으로 지정하는 것과 동일합니다. [SMIL3]

<rect width="100" height="100">
  <animateTransform attributeName="transform" attributeType="XML"
    type="scale" by="1" dur="5s" fill="freeze"/>
</rect>

type="scale"by 애니메이션을 수행할 때의 가산 중립 원소는 값 0입니다. 즉, 위 예제의 애니메이션을 수행하면 0초에 사각형이 보이지 않고(애니메이션된 변환 리스트 값이 scale(0)이므로), 5초에 원래 크기로 복귀합니다(애니메이션된 변환 리스트 값이 scale(1)이므로).

8.3. SVG 1.1 'attributeName' 속성

SVG 1.1 애니메이션은 "attributeName" 속성을 정의하여 대상 속성의 이름을 지정합니다. 표시 속성 gradientTransformpatternTransform 에도 transform 값을 사용할 수 있습니다. 동일한 transform 속성이 애니메이션됩니다.

이 예에서는 linear gradient의 gradient 변환이 애니메이션됩니다.

<linearGradient gradientTransform="scale(2)">
  <animate attributeName="gradientTransform" from="scale(2)" to="scale(4)"
    dur="3s" additive="sum"/>
  <animate attributeName="transform" from="translate(0, 0)" to="translate(100px, 100px)"
    dur="3s" additive="sum"/>
</linearGradient>

linearGradient 요소는 gradientTransform 표시 속성을 지정합니다. 두 개의 animate 요소는 gradientTransformtransform 속성을 대상으로 지정합니다. 모든 애니메이션은 동일한 gradient 변환에 적용되며, 첫 번째 애니메이션의 스케일링을 적용한 후 두 번째 애니메이션의 이동을 순차적으로 적용합니다.

9. 변환 함수

transform 속성의 값은 <transform-function> 목록입니다. 허용되는 변환 함수 집합은 아래와 같습니다. 아래 함수에서 <zero>0deg와 동일하게 동작합니다("단위 없는 0" 각도는 레거시 호환성 유지를 위해 보존됨). 수평 이동의 백분율은 기준 박스의 너비를 기준으로 합니다. 수직 이동의 백분율은 기준 박스의 높이를 기준으로 합니다.

9.1. 2D 변환 함수

matrix() = matrix( <number> [, <number> ]{5,5} )

여섯 값 a, b, c, d, e, f의 변환 행렬 형태로 2D 변환을 지정합니다.

translate() = translate( <length-percentage> [, <length-percentage> ]? )

벡터 [tx, ty]에 의해 2D 이동을 지정합니다. tx는 첫 번째 이동값 매개변수이고, ty는 선택적 두 번째 이동값 매개변수입니다. <ty>가 제공되지 않으면, ty 값은 0입니다.

translateX() = translateX( <length-percentage> )

주어진 값만큼 X 방향으로 이동을 지정합니다.

translateY() = translateY( <length-percentage> )

주어진 값만큼 Y 방향으로 이동을 지정합니다.

scale() = scale( <number> [, <number> ]? )

두 매개변수로 설명되는 [sx,sy] 스케일링 벡터에 의해 2D 스케일 동작을 지정합니다. 두 번째 매개변수가 없으면 첫 번째와 동일한 값을 가집니다. 예를 들어, scale(1, 1)은 요소에 아무런 변화가 없고, scale(2, 2)는 X, Y축 모두 두 배로 보이므로 일반 기하학적 크기의 네 배가 됩니다.

scaleX() = scaleX( <number> )

sx를 매개변수로 사용하여 [sx,1] 스케일링 벡터로 2D 스케일 동작을 지정합니다.

scaleY() = scaleY( <number> )

sy를 매개변수로 사용하여 [1,sy] 스케일링 벡터로 2D 스케일 동작을 지정합니다.

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

매개변수로 지정된 각도만큼, transform-origin 속성에 정의된 원점을 기준으로 2D 회전을 지정합니다. 예를 들어 rotate(90deg)는 요소를 시계 방향으로 4분의 1 회전시킵니다.

skew() = skew( [ <angle> | <zero> ] [, [ <angle> | <zero> ] ]? )

X와 Y에 대해 [ax,ay]로 2D 기울이기(skew)를 지정합니다. 두 번째 매개변수가 없으면 0 값입니다.

skew()는 호환성 유지를 위해 존재하며, 새로운 콘텐츠에서는 사용하지 않는 것이 좋습니다. 대신 skewX() 또는 skewY()를 사용하세요. skew()의 동작은 skewX()skewY()를 곱한 것과 다름에 유의하세요.

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

주어진 각도로 X축 방향 2D 기울이기(skew) 변환을 지정합니다.

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

주어진 각도로 Y축 방향 2D 기울이기(skew) 변환을 지정합니다.

9.2. 변환 함수 원시 및 파생 함수

일부 변환 함수는 더 일반적인 변환 함수로 표현할 수 있습니다. 이러한 변환 함수는 파생 변환 함수(derived transform functions)라 하며, 일반 변환 함수는 원시 변환 함수(primitive transform functions)라 합니다. 2차원 원시 및 파생 변환 함수는 다음과 같습니다:

translate()
<translateX()>, <translateY()>, <translate()>의 원시 함수입니다.
scale()
<scaleX()>, <scaleY()>, <scale()>의 원시 함수입니다.

10. 변환 함수 목록

<transform-function> 목록이 제공되면, 각 변환 함수가 지정된 순서대로 개별적으로 지정된 것과 동일한 효과가 있습니다.

즉, 위치와 크기에 영향을 주는 다른 스타일이 없는 경우, 중첩된 변환 집합은 하나의 변환 함수 목록과 동일하며, 조상 좌표계에서 해당 요소의 로컬 좌표계로 적용됩니다. 결과 변환은 목록의 변환들을 행렬 곱셈한 값입니다.

예시:
<div style="transform: translate(-10px, -20px) scale(2) rotate(45deg)"/>

는 다음과 기능적으로 동일합니다:

<div style="transform: translate(-10px, -20px)" id="root">
  <div style="transform: scale(2)">
    <div style="transform: rotate(45deg)">
    </div>
  </div>
</div>

변환 함수로 인해 객체의 현재 변환 행렬이 역행렬 불가능(non-invertible)이 되면, 해당 객체와 그 콘텐츠는 표시되지 않습니다.

다음 예시의 객체는 0으로 스케일됩니다.

<style>
.box {
  transform: scale(0);
}
</style>

<div class="box">
  Not visible
</div>

스케일링으로 인해 div 박스의 좌표 공간에서 역행렬 불가능한 CTM이 생성됩니다. 따라서 div 박스와 그 안의 텍스트는 표시되지 않습니다.

11. 변환의 보간

보간은 다음과 같이 수행됩니다:

특정 경우, 애니메이션으로 인해 변환 행렬이 특이(singular)하거나 역행렬 불가능(non-invertible)하게 될 수 있습니다. 예를 들어 scale이 1에서 -1로 이동하는 애니메이션. 이때 행렬이 그런 상태에 있으면 변환된 요소는 렌더링되지 않습니다.

12. 원시 및 파생 변환 함수의 보간

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

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)으로 변환됩니다. 이후 두 변환 함수는 수치적으로 보간됩니다.

13. 행렬의 보간

두 행렬 사이를 보간할 때, 각 행렬은 대응하는 이동, 회전, 스케일, 기울기(skew)로 분해됩니다. 분해된 행렬의 각 컴포넌트는 수치적으로 보간되어 마지막 단계에서 행렬로 다시 합성됩니다.

다음 예시에서 요소는 X, Y 방향으로 100픽셀 이동되고, hover 시 1170° 회전합니다. 초기 변환은 45°입니다. transition을 사용하면 저자는 3과 1/4 회전(1170°)의 애니메이션을 기대할 수 있습니다.
<style>
div {
  transform: rotate(45deg);
}
div:hover {
  transform: translate(100px, 100px) rotate(1215deg);
  transition: transform 3s;
}
</style>

<div></div>

소스 변환 rotate(45deg)의 변환 함수 개수가 대상 변환 translate(100px, 100px) rotate(1125deg)의 함수 개수와 다릅니다. 변환의 보간 마지막 규칙에 따라 두 변환 모두 행렬 보간을 사용해야 합니다. 변환 함수를 행렬로 변환하면 세 번 회전 정보가 사라지고 요소는 1/4 회전(90°)만 수행됩니다.

위와 같이 3과 1/4 회전을 얻으려면, 소스와 대상 변환 모두 변환의 보간의 세 번째 규칙을 충족해야 합니다. 소스 변환은 translate(0, 0) rotate(45deg)와 같이 작성해야 변환 함수의 선형 보간이 가능합니다.

아래에서는 2D 행렬의 보간과 행렬 중 하나라도 2D 행렬이 아닌 경우의 행렬 보간을 구분합니다.

보간에 사용되는 행렬 중 하나가 역행렬 불가능한 경우, 사용되는 애니메이션 함수는 해당 애니메이션 명세의 규칙에 따라 불연속 애니메이션(discrete animation)으로 대체되어야 합니다.

13.1. 지원 함수

다음 섹션의 의사 코드는 아래 지원 함수를 사용합니다:

지원 함수(point는 3컴포넌트 벡터, matrix는 4x4 행렬, vector는 4컴포넌트 벡터):
  double  determinant(matrix)          matrix의 4x4 행렬식 반환
  matrix  inverse(matrix)              전달된 행렬의 역행렬 반환
  matrix  transpose(matrix)            전달된 행렬의 전치행렬 반환
  point   multVecMatrix(point, matrix) point를 matrix에 곱하여 변환된 point 반환
  double  length(point)                벡터의 길이 반환
  point   normalize(point)             point를 길이 1로 정규화
  double  dot(point, point)            두 point의 내적 반환
  double  sqrt(double)                 값의 제곱근 반환
  double  max(double y, double x)      두 값 중 더 큰 값 반환
  double  dot(vector, vector)         두 vector의 내적 반환
  vector  multVector(vector, vector)  두 vector 곱셈
  double  sqrt(double)                값의 제곱근 반환
  double  max(double y, double x)     두 값 중 더 큰 값 반환
  double  min(double y, double x)     두 값 중 더 작은 값 반환
  double  cos(double)                 값의 코사인 반환
  double  sin(double)                 값의 사인 반환
  double  acos(double)                값의 아크코사인 반환
  double  abs(double)                  값의 절대값 반환
  double  rad2deg(double)              라디안을 도 단위로 변환해 반환
  double  deg2rad(double)              도 단위를 라디안으로 변환해 반환

분해에는 다음 함수도 사용됨:
  point combine(point a, point b, double ascl, double bscl)
      result[0] = (ascl * a[0]) + (bscl * b[0])
      result[1] = (ascl * a[1]) + (bscl * b[1])
      result[2] = (ascl * a[2]) + (bscl * b[2])
      return result

13.2. 2D 행렬의 보간

13.2.1. 2D 행렬 분해

아래 의사 코드는 "Graphics Gems II, Jim Arvo 편집"의 "unmatrix" 방법에 기반합니다.

의사 코드의 행렬은 컬럼 우선(column-major) 순서를 사용합니다. 행렬 항목의 첫 번째 인덱스는 컬럼, 두 번째 인덱스는 행을 나타냅니다.

입력:  matrix      ; 4x4 행렬
출력: translation ; 2컴포넌트 벡터
        scale       ; 2컴포넌트 벡터
        angle       ; 회전
        m11         ; 2x2 행렬의 1,1
        m12         ; 2x2 행렬의 1,2
        m21         ; 2x2 행렬의 2,1
        m22         ; 2x2 행렬의 2,2
분해 불가시 false, 가능하면 true 반환

double row0x = matrix[0][0]
double row0y = matrix[0][1]
double row1x = matrix[1][0]
double row1y = matrix[1][1]

translate[0] = matrix[3][0]
translate[1] = matrix[3][1]

scale[0] = sqrt(row0x * row0x + row0y * row0y)
scale[1] = sqrt(row1x * row1x + row1y * row1y)

// 행렬식이 음수면 한 축이 뒤집힘.
double determinant = row0x * row1y - row0y * row1x
if (determinant < 0)
    // 최소 단위벡터 내적이 작은 축을 뒤집기.
    if (row0x < row1y)
        scale[0] = -scale[0]
    else
        scale[1] = -scale[1]

// 스케일 제거를 위해 행렬 재정규화.
if (scale[0])
    row0x *= 1 / scale[0]
    row0y *= 1 / scale[0]
if (scale[1])
    row1x *= 1 / scale[1]
    row1y *= 1 / scale[1]

// 회전 계산 및 행렬 재정규화.
angle = atan2(row0y, row0x);

if (angle)
    // Rotate(-angle) = [cos(angle), sin(angle), -sin(angle), cos(angle)]
    //                = [row0x, -row0y, row0y, row0x]
    // 위 정규화 덕분에.
    double sn = -row0y
    double cs = row0x
    double m11 = row0x
    double m12 = row0y
    double m21 = row1x
    double m22 = row1y
    row0x = cs * m11 + sn * m21
    row0y = cs * m12 + sn * m22
    row1x = -sn * m11 + cs * m21
    row1y = -sn * m12 + cs * m22

m11 = row0x
m12 = row0y
m21 = row1x
m22 = row1y

// 회전 함수가 도 단위를 기대하므로 변환.
angle = rad2deg(angle)

return true

13.2.2. 분해된 2D 행렬 값의 보간

두 분해된 2D 행렬 값을 보간하기 전에 다음을 수행합니다

입력: translationA ; 2컴포넌트 벡터
       scaleA       ; 2컴포넌트 벡터
       angleA       ; 회전
       m11A         ; 2x2 행렬의 1,1
       m12A         ; 2x2 행렬의 1,2
       m21A         ; 2x2 행렬의 2,1
       m22A         ; 2x2 행렬의 2,2
       translationB ; 2컴포넌트 벡터
       scaleB       ; 2컴포넌트 벡터
       angleB       ; 회전
       m11B         ; 2x2 행렬의 1,1
       m12B         ; 2x2 행렬의 1,2
       m21B         ; 2x2 행렬의 2,1
       m22B         ; 2x2 행렬의 2,2


// 하나는 x축, 다른 하나는 y축이 뒤집혔다면,
// 뒤집히지 않은 회전으로 변환.
if ((scaleA[0] < 0 && scaleB[1] < 0) || (scaleA[1] < 0 && scaleB[0] < 0))
    scaleA[0] = -scaleA[0]
    scaleA[1] = -scaleA[1]
    angleA += angleA < 0 ? 180 : -180

// 긴 방향으로 돌지 않도록.
if (!angleA)
    angleA = 360
if (!angleB)
    angleB = 360

if (abs(angleA - angleB) > 180)
    if (angleA > angleB)
        angleA -= 360
    else
        angleB -= 360

이후, 소스 행렬의 분해값 translation, scale, angle, m11~m22의 각 컴포넌트는 대상 행렬의 해당 컴포넌트와 선형적으로 보간됩니다.

13.2.3. 2D 행렬로 재합성

보간 후, 결과값은 요소의 사용자 공간 변환에 사용됩니다. 한 가지 방법은 이 값들을 다시 4x4 행렬로 합성하는 것입니다. 아래 의사 코드에 따라 수행할 수 있습니다.

의사 코드의 행렬은 컬럼 우선(column-major) 순서를 사용합니다. 행렬 항목의 첫 번째 인덱스는 컬럼, 두 번째 인덱스는 행을 나타냅니다.

입력:  translation ; 2컴포넌트 벡터
        scale       ; 2컴포넌트 벡터
        angle       ; 회전
        m11         ; 2x2 행렬의 1,1
        m12         ; 2x2 행렬의 1,2
        m21         ; 2x2 행렬의 2,1
        m22         ; 2x2 행렬의 2,2
출력: matrix      ; 항등 행렬로 초기화된 4x4 행렬

matrix[0][0] = m11
matrix[0][1] = m12
matrix[1][0] = m21
matrix[1][1] = m22

// 행렬 이동.
matrix[3][0] = translate[0] * m11 + translate[1] * m21
matrix[3][1] = translate[0] * m12 + translate[1] * m22

// 행렬 회전.
angle = deg2rad(angle);
double cosAngle = cos(angle);
double sinAngle = sin(angle);

// 임시, 항등 행렬로 초기화된 4x4 행렬 rotateMatrix
rotateMatrix[0][0] = cosAngle
rotateMatrix[0][1] = sinAngle
rotateMatrix[1][0] = -sinAngle
rotateMatrix[1][1] = cosAngle

matrix = post-multiply(rotateMatrix, matrix)

// 행렬 스케일.
matrix[0][0] *= scale[0]
matrix[0][1] *= scale[0]
matrix[1][0] *= scale[1]
matrix[1][1] *= scale[1]

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

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

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

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

15. 프라이버시 및 보안 고려사항

UA는 공격자가 정보를 유추하거나 타이밍 공격을 할 수 없도록 변환 연산을 구현해야 합니다.

타이밍 공격이란, 연산이 수행되는 시간 차이를 분석하여 보호된 콘텐츠 정보를 얻는 방법입니다.

현재 이 명세에 특화된 잠재적 프라이버시 또는 보안 문제에 대한 정보는 없습니다.

변경 사항

2018년 11월 30일 워킹 드래프트 이후

2017년 11월 30일 워킹 드래프트 이후

감사의 글

편집자들은 Robert O’Callahan, Cameron McCormack, Tab Atkins, Gérard Talbot, L. David Baron, Rik Cabanier, Brian Birtles, Benoit Jacob, Ken Shoemake, Alan Gresley, Maciej Stochowiak, Sylvain Galineau, Rafal Pietrak, Shane Stephens, Matt Rakow, XiangHongAi, Fabio M. Costa, Nivesh Rajbhandari, Rebecca Hauck, Gregg Tavares, Graham Clift, Erik Dahlström, Alexander Zolotov, Amelia Bellamy-Royds, Boris Zbarsky에게 꼼꼼한 리뷰, 코멘트, 수정에 대해 감사드립니다.

적합성

문서 관례

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

이 명세서의 모든 텍스트는 명시적으로 비규범적임이 표시된 섹션, 예제, 참고를 제외하고는 규범적입니다. [RFC2119]

이 명세서에서 예제는 “for example”로 시작하거나 class="example"로 규범적 텍스트와 구분되어 아래처럼 표시됩니다:

이것은 참고용 예제입니다.

참고 노트는 “Note”로 시작하며, class="note"로 규범적 텍스트와 구분되어 아래처럼 표시됩니다:

참고, 이것은 참고용 노트입니다.

권고 사항(advisement)은 특별한 주의를 환기시키기 위해 스타일링된 규범 섹션이며, <strong class="advisement">로 규범 텍스트와 구분되어 아래처럼 표시됩니다: UA는 반드시 접근 가능한 대체 수단을 제공해야 합니다.

적합성 클래스

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

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

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

렌더러가 이 명세서에 적합하려면, 적절한 명세서에 따라 스타일 시트를 해석하는 것 외에도, 이 명세서에서 정의된 모든 기능을 올바르게 파싱하고 적절하게 문서를 렌더링함으로써 지원해야 합니다. 다만, UA가 기기 제한으로 인해 문서를 올바르게 렌더링하지 못하는 경우, UA가 비적합한 것은 아닙니다. (예: UA가 모노크롬 모니터에서 색상을 렌더링할 필요는 없음)

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

CSS의 책임 구현 요구 사항

다음 섹션은 현재와 미래의 상호운용성을 촉진할 수 있도록 CSS를 책임감 있게 구현하기 위한 여러 적합성 요구사항을 정의합니다.

부분 구현

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

불안정 및 독점 기능 구현

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

CR 단계 기능의 구현

명세서가 후보 권고(CR) 단계에 도달하면, 구현자는 명세대로 올바르게 구현했음을 입증할 수 있는 CR 단계 기능의 접두어 없는 구현을 출시해야 하며, 해당 기능의 접두어 변형을 노출하는 것은 피해야 합니다.

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

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

CR 종료 기준

이 명세가 제안 권고(Proposed Recommendation)로 진전되려면, 각 기능별로 두 개 이상의 독립적이고 상호운용 가능한 구현이 있어야 합니다. 각 기능은 서로 다른 제품 집합에 의해 구현될 수 있으며, 모든 기능이 단일 제품에서 구현될 필요는 없습니다. 이 기준에 대해 다음 용어를 정의합니다:

독립적
각 구현은 다른 당사자에 의해 개발되어야 하며, 다른 구현에서 사용된 코드를 공유, 재사용, 파생할 수 없습니다. 해당 명세 구현과 관련 없는 코드 부분은 예외입니다.
상호운용 가능
공식 CSS 테스트 스위트의 해당 테스트케이스를 통과하거나, 웹 브라우저가 아닌 경우 동등한 테스트를 통과해야 합니다. 테스트 스위트의 모든 관련 테스트에 대해 동등한 테스트를 생성해야 하며, 해당 UA(사용자 에이전트)로 상호운용성을 주장하려면 동등 테스트를 통과하는 하나 이상의 추가 UA도 있어야 합니다. 동등 테스트는 동료 검토를 위해 공개되어야 합니다.
구현체
다음을 만족하는 사용자 에이전트:
  1. 명세를 구현함.
  2. 일반에 공개되어 있음. 구현체는 출시 제품 또는 베타, 프리뷰, "nightly build" 등 공개 버전일 수 있음. 출시되지 않은 제품 버전은 최소 한 달간 해당 기능을 구현해 안정성을 입증해야 함.
  3. 실험적이지 않음(테스트 스위트 통과만을 목적으로 만들어진 버전이 아니며, 향후 일반 사용을 위한 버전임).

명세는 최소 6개월간 후보 권고(Candidate Recommendation)로 유지됩니다.

색인

이 명세서에서 정의한 용어

참조로 정의된 용어

참고문헌

표준 참고문헌

[CSS-CASCADE-4]
Elika Etemad; Tab Atkins Jr.. CSS Cascading and Inheritance Level 4. 2018년 8월 28일. CR. URL: https://www.w3.org/TR/css-cascade-4/
[CSS-MASKING]
Dirk Schulze; Brian Birtles; Tab Atkins Jr.. CSS Masking Module Level 1. 2014년 8월 26일. CR. URL: https://www.w3.org/TR/css-masking-1/
[CSS-OVERFLOW-3]
David Baron; Elika Etemad; Florian Rivoal. CSS Overflow Module Level 3. 2018년 7월 31일. WD. URL: https://www.w3.org/TR/css-overflow-3/
[CSS-POSITION-3]
Rossen Atanassov; Arron Eicholz. CSS Positioned Layout Module Level 3. 2016년 5월 17일. WD. URL: https://www.w3.org/TR/css-position-3/
[CSS-SYNTAX-3]
Tab Atkins Jr.; Simon Sapin. CSS Syntax Module Level 3. 2014년 2월 20일. CR. URL: https://www.w3.org/TR/css-syntax-3/
[CSS-VALUES-3]
Tab Atkins Jr.; Elika Etemad. CSS Values and Units Module Level 3. 2018년 8월 14일. 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. 2018년 10월 10일. WD. URL: https://www.w3.org/TR/css-values-4/
[CSS2]
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/CSS2/
[CSS3BG]
Bert Bos; Elika Etemad; Brad Kemper. CSS Backgrounds and Borders Module Level 3. 2017년 10월 17일. CR. URL: https://www.w3.org/TR/css-backgrounds-3/
[CSSOM]
Simon Pieters; Glenn Adams. CSS Object Model (CSSOM). 2016년 3월 17일. WD. URL: https://www.w3.org/TR/cssom-1/
[RFC2119]
S. Bradner. Key words for use in RFCs to Indicate Requirement Levels. 1997년 3월. Best Current Practice. URL: https://tools.ietf.org/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-TRANSFORMS-2]
CSS Transforms Module Level 2 URL: https://drafts.csswg.org/css-transforms-2/
[CSSOM-VIEW]
Simon Pieters. CSSOM View Module. 2016년 3월 17일. WD. URL: https://www.w3.org/TR/cssom-view-1/
[HTML]
Anne van Kesteren; et al. HTML Standard. Living Standard. URL: https://html.spec.whatwg.org/multipage/
[SMIL]
Philipp Hoschka. Synchronized Multimedia Integration Language (SMIL 2.0) - [Second Edition]. 2005년 1월 7일. REC. URL: https://www.w3.org/TR/SMIL/
[SMIL3]
Dick Bulterman. Synchronized Multimedia Integration Language (SMIL 3.0). 2008년 12월 1일. REC. URL: https://www.w3.org/TR/SMIL3/

속성 색인

이름 초기값 적용 대상 상속 백분율 애니메이션 타입 정준 순서 계산값
transform none | <transform-list> none 변환 가능한 요소 아니오 기준 박스 크기 기준 transform list, 보간 규칙 참조 문법 순서 지정값, 단 길이는 절대값으로 변환
transform-box content-box | border-box | fill-box | stroke-box | view-box view-box 변환 가능한 요소 아니오 해당 없음 불연속 문법 순서 지정된 키워드
transform-origin [ left | center | right | top | bottom | <length-percentage> ] |   [ left | center | right | <length-percentage> ]  [ top | center | bottom | <length-percentage> ] <length>? |  [[ center | left | right ] && [ center | top | bottom ]] <length>? 50% 50% 변환 가능한 요소 아니오 기준 박스 크기 기준 계산값 기준 문법 순서 background-position 참조