Figma와 브라우저의 1px에 대하여

김도은 · 원프레딕트 프론트엔드 엔지니어
July 09, 2024

Intro.

원프레딕트 디자인 시스템을 구축, 개발하고 있습니다.

Figma 컴포넌트에는 Token Studio for Figma (Figma Token) Plugin을 사용하여 디자인 토큰을 관리, 적용하고 있습니다.

Figma 디자인 요소를 브라우저에 구현할 때 1px의 차이가 발생하였으며, 이 문제의 원인과 해결책을 기록한 글입니다.

Figma 기능

Auto Layout의 Strokes 기능

Figma의 Auto Layout 기능은 디자인 요소를 자동으로 정렬하고 배치하는 데 유용한 도구입니다. 요소의 자동 정렬, 배치, 간격, 패딩, 크기 조정 등을 할 수 있으며, 여러 요소에 일괄 적용할 수 있어 효율적으로 디자인 작업을 할 수 있습니다.

Auto Layout의 Strokes 기능은 Auto Layout의 크기 계산에 외곽선 너비를 포함할 지 여부를 결정합니다. 즉, Auto Layout이 설정된 영역(박스) 내 요소들의 간격을 계산하는 방식이 달라집니다. Auto layout > Strokes는 Included, Excluded 중 하나를 선택할 수 있습니다.

  • Strokes가 Included인 경우 : Auto Layout의 크기 계산에 border width가 요소 크기에 포함되며, 요소의 padding도 크기에 포함됩니다.
  • Strokes가 Excluded인 경우 : Auto Layout의 크기 계산에 border width가 포함되지 않습니다. 요소의 padding 간격에 border를 무시한 채로 계산됩니다.

요소의 Stroke 기능

컨텐츠 영역을 기준으로 요소의 외곽선을 내부에 그릴 것인지 외부에 그릴 것인지 결정합니다.

  • Stroke가 Inside인 경우 : 컨텐츠 영역을 기준으로 안쪽에 외곽선을 그립니다.
  • Stroke가 Outside인 경우 : 컨텐츠 영역을 기준으로 바깥쪽에 외곽선을 그립니다.

요소를 배치하고 외곽선을 그리는 방식

Auto Layout > Strokes 옵션과 요소의 Stroke 옵션을 조합하면 4가지 조합의 방식으로 디자인할 수 있습니다.

border : 2px, padding left/right : 4px, padding top/bottom : 4px의 요소를 대상으로 4가지 조합 방식을 적용하여 설명해 보겠습니다.

  1. Auto Layout Strokes를 Included로, 요소 Stroke를 Inside인 경우

    Auto layout > Strokes : Included / Stroke : Inside

    위 요소의 width는 19px입니다.

    width 19px인 이유 = border left(2) + padding left(4) + contents(7) + padding right(4) + border right(2)

  2. Auto Layout Strokes를 Excluded로, 요소 Stroke를 Inside인 경우

    Auto layout > Strokes : Excluded / Stroke : Inside

    위 요소의 width는 15px입니다.

    width 15px인 이유 = padding left(4) + contents(7) + padding right(4)

    이 경우에는 width 계산 시에 border width가 계산되지 않습니다.

  3. Auto Layout Strokes를 Included로, 요소 Stroke를 Outside인 경우

    Auto layout > Strokes : Included / Stroke : Outside

    Figma Frame 정보창에서의 width는 15px로 표기되나, 실제의 width는 19px입니다.

    실제 width 19px인 이유 = border left(2) + padding left(4) + contents(7) + padding right(4) + border right(2)

    이 경우는 우측 정보창의 width와 실제로 보여지는 width가 다릅니다.

  4. Auto Layout Strokes를 Excluded로, 요소 Stroke를 Outside인 경우

    Auto layout > Strokes : Excluded / Stroke : Outside

    3번 케이스와 동일하게 Figma Frame 정보창에서의 width는 15px로 표기되나, 실제의 width는 19px입니다.

    실제 width 19px인 이유 = border left(2) + padding left(4) + contents(7) + padding right(4) + border right(2)

    이 경우는 우측 정보창의 width와 실제로 보여지는 width가 다릅니다.

4가지 케이스를 모두 살펴본 결과 다음과 같은 결론을 내릴 수 있습니다.

  • Auto Layout의 Strokes를 Excluded인 경우에는 padding과 border width가 겹쳐집니다.
  • Stroke가 Outside인 경우는 Figma 정보창에서 표기되는 크기와 실제 크기가 다릅니다.

브라우저

브라우저에서 요소를 그리는 방식

Browser CSS Box Model

웹 브라우저에서 요소를 그리는 방식은 CSS Box Model을 사용합니다. 이 모델을 통해 일관된 규칙에 따라 그려지며 동작합니다.

border와 관련있는 속성은 box-sizing이며, 해당 속성의 값은 border-box, content-box 중 하나를 가집니다.

  1. box-sizing: border-box인 경우

    boder: 2px solid gray
    border-radius: 4px
    width: 15px
    height: 28px
    box-sizing: border-box

    위와 같이 스타일을 적용하였을 때 다음과 같이 렌더링됩니다.

    box-sizing이 border-box인 경우

    개발자가 설정한 width는 15px이며, 실제로 보여지는 width도 15px입니다.

  2. box-sizing: content-box인 경우

    boder: 2px solid gray
    border-radius: 4px
    width: 15px
    height: 28px
    box-sizing: content-box

    위와 같이 스타일을 적용하였을 때 다음과 같이 렌더링됩니다.

    box-sizing이 content-box인 경우

    개발자가 설정한 width는 15px이며, 실제로 보여지는 width는 19px입니다.

개발 시 css에 box-sizing을 border-box로 선호하는 이유

css에서 box-sizing 을 border-box로 하는 이유 블로그 글을 참고하자면

  1. 직관적인 크기 계산

    • border-box의 경우 설정한 사이즈가 브라우저에 보여지는 사이즈와 같아서 요소의 실제 크기를 예측하기 쉬워집니다.
    • content-box의 경우 border가 컨텐츠 영역 밖에 그려지므로 설정한 사이즈와 다르게 그려지며,

    javascript로 요소의 크기를 이용하여 계산하는 로직이 있는 경우 box-sizing에 따라 분기처리를 한다거나 하는 등의 계산을 해야합니다.

  2. 레이아웃 일관성

    • border-box의 경우 버튼 컴포넌트와 같은 요소의 크기가 항상 일정하게 유지되므로, 복잡한 레이아웃 구성인 경우 일관성을 유지하기 쉽습니다.
    • 또한, padding, border width가 변경되더라도 요소의 전체 크기가 변경되지 않기 때문에 안정적으로 브라우저 위에 보여지게 됩니다.
  3. 브라우저 호환성 등

    • 다양한 브라우저와의 호환성과 css 스타일 획일화를 위해 border-box 방식을 선호합니다.

과 같은 이유로 개발 시에는 box-sizing을 border-box를 선정하게 되었습니다.

Figma에서 Auto Layout은 브라우저에서 어떤 기능과 유사한가?

CSS Box Model에 따라서 box-sizing을 border-box인 경우 Figma에서 Auto Layout > Strokes를 Included로, 요소의 Stroke를 Inside인 경우와 동일합니다. 그리고 css에서 border가 아닌 outline을 사용하는 경우는 요소의 Stroke가 Outside인 경우와 동일합니다.

그 외 발생했던 문제들

요소의 Stroke가 Outside인 경우의 문제

아래는 Stroke가 Outside인 버튼 요소와 버튼 사이에 gap을 설정한 이미지입니다. 버튼과 버튼 사이의 gap을 20px을 주었지만, stroke가 Outside이므로 실제 간격의 수치와 다르게 그려집니다.

요소의 Stroke를 Inside, Outside로 혼용 시의 문제

요소의 Stroke가 Outside인 경우 하나의 요소만 있는 경우는 상관없으나, 여러 요소들이 Auto Layout으로 잡혀있고 gap을 입력하게 되는 경우 문제가 발생합니다.

Different El Stroke Problem

위에서 언급한 gap의 문제가 이 경우에서도 발생합니다. 오히려 Stroke의 방식이 혼용되어 사이 값 수치를 계산하기 어렵습니다.

요소의 Stroke가 Outside인 경우 요소의 실제 사이즈가 고정안되는 문제

요소의 Stroke가 Outside인 경우 Figma에서 입력한 사이즈에서 border width만큼 더 커지게 그려지는 현상이 발생합니다. 그러므로 border width가 두꺼워질수록 실제 사이즈가 커지게 됩니다.

예시

외곽선이 있는 버튼 컴포넌트 디자인

디자이너가 지정한 버튼 컴포넌트의 size와 padding의 measurement는 다음과 같습니다.

Border Variant Button Component

  • 위 버튼 컴포넌트는 border를 가지는 형태입니다.
  • 위 버튼 컴포넌트는 small 사이즈입니다.
  • small 사이즈 버튼 컴포넌트 내부의 gap은 4px입니다.
  • 버튼 컴포넌트 앞/뒤에 아이콘이 위치할 수 있습니다.
  • small 사이즈 버튼 컴포넌트의 Height는 28px입니다.
  • 앞/뒤에 아이콘이 모두 위치한 경우 small 사이즈 버튼 컴포넌트의 Width는 94px입니다.

이 때, 디자이너가 Figma에서 구현한 버튼 컴포넌트의 사이즈가 Plugin을 통해 CSS 코드로 변환한 값과 일치하려면 다음과 같이 설정해야 합니다.

Border Variant Button Component At CSS Box Model

  • Auto Layout의 Strokes를 Included
  • 요소의 Stroke를 Inside
  • Padding Left/Right를 11px
  • Padding Top/Bottom을 5px
  • Border Width를 1px

즉, 외곽선이 있는 요소는 border width를 고려하여 padding, gap의 값을 설정하여야 합니다.

Auto Layout의 Strokes를 Excluded하고 padding을 12px로 border width를 1px로 설정하면 실제로 버튼 컴포넌트의 Width가 94px보다 크게 그려집니다.

채워진 버튼 컴포넌트 디자인

외곽선이 없는 채워진 버튼 컴포넌트의 설정은 다음과 같습니다.

Filled Variant Button Component

Filled Variant Button Component At CSS Box Model

외곽선이 없는 경우에는 Auto Layout의 Strokes가 어떤 값이든 상관없이 동일하게 보여집니다.

결론

디자인 시스템은 일관된 규칙을 가져야 하며, 개발자와 디자이너 간에 이해가 필요합니다.

우리는 위에서 Figma에서 디자인을 하는 방식과 브라우저의 CSS Box Model에 대해 다루어 보았습니다.

결과적으로 디자인 시스템을 통해 Figma 위에 그려진 요소의 디자인과 속성 값이 브라우저 위에서도 동일하게 구현되기를 원합니다.

  • Figma에 입력된 사이즈(픽셀)이 Figma 위에 그려지는 요소의 사이즈(픽셀)와 동일하여야 하며,
  • Figma를 통해 변환되어 나오는 CSS 속성을 브라우저 위에 구현하였을 때 동일하게 렌더링되어야 합니다.

우선 위에서 다루었던 Figma의 Auto Layout, Stroke 옵션들의 4가지 경우를 비교해보겠습니다.

No. AutoLayout의 Strokes 요소의 Stroke Figma 사이즈 = 렌더링 사이즈 (pixel) 외곽선 두께에 따른 요소 실제 사이즈 변화 Figma 디자인을 css로 구현하는 방법
1 Included Inside 일치 변경 안됨 border, padding
2 Excluded Inside 일치 변경 안됨 padding, box-shadow
3 Included Outside 불일치 외곽선 두께에 따라 변경 outline, padding
4 Excluded Outside 불일치 외곽선 두께에 따라 변경 outline, padding

외곽선이 있는 디자인 요소를 브라우저에서 동일하게 표현하기 위한 Figma 옵션은 1번 케이스입니다. 그리고 외곽선을 그리기 위해 border 속성이 아닌 box-shadow 속성을 사용하는 경우에는 2번 케이스도 동일하게 표현이 가능합니다.

일반적으로 외곽선을 border 속성으로 표현하므로 Figma 상에서 Auto Layout의 Strokes는 Included, 요소의 Stroke는 Inside로 설정되어야 브라우저의 CSS Box Model과 일치되어 1px의 오차도 없이 구현될 것입니다.

원프레딕트는 더 나은 제품을 고민하며 기술적인 문제를 함께 풀어낼 동료를 찾고 있습니다.
자세한 내용은 채용 사이트를 참고해 주세요.