CSS box로 도형 만들기
이제 본격적으로 CSS로 도형을 만들어봅시다.
브라우저에서 가장 기본적인 도형은 무엇일까요? 원? 선? 삼각형?
아쉽지만 정답은 박스입니다. CSS는 일단 모든 것을 사각형 박스로 봅니다. 글자도 박스 안에 있고, 버튼도 박스고, 이미지도 박스고, 우리가 만들 rectangle primitive도 결국 박스입니다. 브라우저는 은근히 사각형을 좋아합니다.
박스는 편집기의 rectangle primitive다
Figma 같은 에디터에서 사각형을 하나 만들면 모델에는 대략 이런 값이 들어갑니다.
x, y, width, height, fill, stroke, radius
CSS box도 비슷합니다.
left: 120px;
top: 80px;
width: 160px;
height: 100px;
background: #7c9cff;
border: 2px solid #26324a;
겉으로는 아주 잘 맞아 보입니다. 그래서 처음에는 DOM 요소 하나를 오브젝트 하나로 보고 시작해도 괜찮습니다. CSS 기반 에디터를 배우는 입장에서는 이 단순함이 큰 장점입니다.
하지만 bounds는 조심스럽다
width와 height만 알면 도형의 크기를 알 수 있을 것 같지만, CSS에는 box-sizing, border, padding, box-shadow 같은 속성들이 있습니다.
contentBox, paddingBox, borderBox를 구분한다.
visualBounds = transformed(borderBox) + decoration overflow
center = (x + width / 2, y + height / 2)
에디터 모델에서 width = 160이라고 했는데 CSS가 content-box이면 padding과 border 때문에 화면에서 더 커질 수 있습니다. 그러면 selection box와 실제 도형이 어긋납니다. 사용자는 “왜 테두리가 삐져나오지?”라고 묻고, 우리는 조용히 box-sizing을 확인하게 됩니다.
그래서 에디터에서는 보통 box-sizing: border-box를 기본으로 잡습니다. 모델의 width, height와 CSS의 width, height를 맞추기 쉬워집니다.
모델 값과 CSS 값을 분리하자
편집기 모델은 CSS 문자열이 아니라 구조화된 값이어야 합니다.
model = {
x,
y,
width,
height,
fill,
stroke,
radius
}
렌더링할 때만 이 값을 CSS style로 바꿉니다. 모델이 진짜 데이터이고, CSS는 화면에 보여주는 결과입니다. 이 구분이 생기면 저장, undo/redo, Canvas 전환도 훨씬 편해집니다.
데모에서 볼 것
데모에서는 border와 padding을 바꾸며 getBoundingClientRect()와 모델 width/height의 관계를 확인합니다.
오늘의 요점은 단순합니다. CSS box는 훌륭한 도형 출발점입니다. 다만 모델 값과 화면 결과를 같은 것으로 착각하면 선택 박스가 삐뚤어집니다. 박스는 착하지만, CSS 박스 모델은 가끔 장난을 칩니다.