CSS Graphics Geometry
Guide
Reference
GitHub
Guide
Reference
GitHub
  • Part 0. Math foundations

    • 좌표계와 CSS pixel
    • 점, 벡터, 거리와 기본 용어
    • 각도, 라디안, atan2
  • Part 1. Transform linear algebra

    • translate, scale, rotate
    • CSS matrix(a,b,c,d,e,f)
    • 변환 순서와 transform-origin
    • local, world, screen 좌표계
    • inverse matrix와 포인터 입력
    • 좌표와 transform 디버깅
  • Part 2. Infinite canvas math and architecture

    • viewport와 camera 모델
    • cursor anchored zoom
    • ruler와 tick 계산
    • 주기 함수와 grid step
    • content, overlay, controls layer
    • scene graph와 nested transform
  • Part 3. Editor tool math

    • Pointer Events와 드래그
    • DOMRect와 getBoundingClientRect
    • hit testing과 bounding box
    • selection rectangle과 marquee
    • selection bounds와 handles
    • resize와 rotation handle
    • snapping과 smart guides
    • group, frame, clipping
  • Part 4. CSS graphics properties as math

    • CSS box로 도형 만들기
    • clip-path, radius, shadow
    • 선형보간과 linear-gradient
    • 거리 함수와 radial/conic-gradient
    • stacking context와 합성
    • layout, paint, composite
  • Part 5. Editor state and persistence

    • 레이어 모델과 z-index
    • 이동, 복제, 삭제, 잠금
    • undo/redo command model
    • JSON export/import
  • Part 6. SVG overlay and vector editing

    • SVG viewBox와 좌표계
    • getScreenCTM과 inverse
    • SVG pointer-events와 stroke hit testing
    • cubic bezier path editing
    • mask, clipPath, marker
  • Part 7. Figma to CSS translation

    • Figma node와 CSS DOM 모델
    • Frame constraints와 Auto Layout
    • Fills, strokes, effects를 CSS로
    • Vector와 text 변환
    • gradient 밖의 CSS 수학
    • Figma gradient를 CSS gradient로 변환하기
    • 수학이 필요한 Figma to CSS 속성들
    • Figma VectorNetwork 정리
  • Appendix A. Canvas renderer transition

    • Canvas로 넘어가는 기준
  • Appendix B. Motion and timing

    • 모션 수학과 timing 함수
    • Keyframe timeline 엔진
    • Motion path 수학
    • Bezier curve 길이 구하기

Figma node와 CSS DOM 모델

이제 Figma에서 만든 디자인을 CSS 기반 에디터나 웹 화면으로 옮기는 이야기를 해봅시다.

여기서 제일 먼저 버려야 할 생각이 하나 있습니다. “Figma node 하나는 div 하나다.” 이 말은 시작점으로는 괜찮지만, 끝까지 믿으면 곧 삐걱댑니다. Figma의 node는 디자인 모델이고, CSS의 DOM은 브라우저가 그릴 구조입니다. 둘은 닮았지만 같은 생물은 아닙니다.

Figma는 scene graph다

Figma 파일 안에는 frame, group, rectangle, vector, text, component instance 같은 node가 tree로 들어 있습니다.

node = {
  id,
  type,
  parentId,
  absoluteTransform,
  relativeTransform,
  size,
  fills,
  strokes,
  effects
}

이 구조는 우리가 앞에서 만든 scene graph와 아주 비슷합니다. 부모 transform이 있고, child가 있고, frame은 clipping과 layout 규칙도 가질 수 있습니다.

Figma node model to CSS DOM diagramFigma scene graphFrameGroupRectangleCSS projection<div class="frame"><div class="group"><div class="rect" /></div></div>model: id, parentId, transform, size, style -> renderer: DOM nodes + CSS styles
Figma node는 scene graph의 데이터이고, CSS 구현은 DOM tree와 style projection입니다. 저장 모델과 렌더링 결과를 분리해야 변환이 오래 갑니다.

Figma transform은 top-left 기준으로 읽는다

Figma node의 relativeTransform은 2x3 affine transform입니다.

T = [
  [a, c, e],
  [b, d, f]
]

local 점을 parent 좌표로 보내면 이렇게 됩니다.

x' = a * x + c * y + e
y' = b * x + d * y + f

여기서 local (0, 0)은 node의 top-left입니다. Figma의 rotation도 top-left 기준으로 해석됩니다. 그래서 CSS DOM으로 투영할 때는 기본 center origin을 그대로 쓰면 안 맞을 수 있습니다.

.node {
  position: absolute;
  width: var(--figma-width);
  height: var(--figma-height);
  transform-origin: 0 0;
  transform: matrix(a, b, c, d, e, f);
}

Figma에는 CSS의 transform-origin처럼 별도 스타일 속성이 있는 게 아니라, transform matrix와 node size를 조합해서 pivot 동작을 만들어야 합니다. center 기준으로 회전시키고 싶다면 center가 부모 좌표에서 고정되도록 e, f를 다시 계산합니다.

pivotLocal = (width / 2, height / 2)
pivotParent = oldMatrix * pivotLocal
newTranslation = pivotParent - newLinearPart * pivotLocal

이 식은 Figma to CSS뿐 아니라 group 안의 child를 frame으로 옮기는 reparenting, rotation handle, resize handle에서도 계속 다시 나옵니다. 결국 “어느 점을 고정할 것인가?”를 정하는 문제입니다.

CSS는 projection이다

CSS 구현에서는 이 모델을 DOM과 style로 투영합니다.

Figma Frame -> div.frame
Figma Group -> div.group or flattened wrapper
Figma Rectangle -> div with width/height/background/border
Figma Vector -> svg path or exported asset
Figma Text -> text element with font styles

여기서 중요한 건 “변환 결과”를 저장 모델로 삼지 않는 겁니다. Figma에서 가져온 원본 구조나 우리가 정리한 중간 모델을 유지하고, 렌더링할 때만 DOM/CSS를 만듭니다. 그래야 다시 export하거나, undo/redo하거나, Canvas 렌더러로 바꿀 때 덜 흔들립니다.

1:1 변환이 안 되는 지점

Figma의 stroke align은 inside, center, outside를 가질 수 있지만 CSS border는 기본적으로 box model 안에 포함되는 방식이 다릅니다. Figma의 layer blur와 background blur도 CSS filter, backdrop-filter와 완전히 같은 모델이 아닐 수 있습니다.

그래서 변환기는 늘 세 가지 선택을 합니다.

1. CSS primitive로 직접 표현한다.
2. wrapper나 pseudo-element를 추가해서 근사한다.
3. SVG나 이미지 asset으로 내보낸다.

완벽한 변환보다 중요한 건 정책이 일관적인 겁니다. 같은 Figma 속성이 어떤 경우에는 div, 어떤 경우에는 svg로 튀면 나중에 디버깅할 때 머리가 살짝 뜨거워집니다.

데모에서 볼 것

데모에서는 Figma node tree가 DOM tree와 CSS style projection으로 어떻게 나뉘는지 봅니다.

오늘의 핵심은 이겁니다. Figma to CSS는 파일을 문자열로 바꾸는 일이 아니라, 한 그래픽 모델을 브라우저 모델로 번역하는 일입니다. 번역가는 단어만 바꾸지 않고 문맥도 봅니다. 우리도 그래야 합니다.

Edit this page
최근 수정: 26. 5. 14. PM 5:45
Contributors: easylogic
Next
Frame constraints와 Auto Layout