피그마 개발 모드에서 인스펙트로 읽은 값을 실제 CSS로 옮기는 일이 핸드오프입니다. 오늘은 도구가 뽑아 준 값을 그대로 붙이는 대신, 관계로 다시 쓰고 토큰으로 정리하는 과정을 코드로 보겠습니다.
66.1 인스펙트 값을 CSS 규칙으로
인스펙트 패널은 요소를 누르면 크기와 색, 간격, 폰트를 숫자로 보여 줍니다. 그 값을 읽어 대응하는 CSS 프로퍼티에 옮기는 것이 첫걸음입니다.
.card {
width: 320px;
padding: 20px;
background: #ffffff;
border-radius: 12px;
font-size: 15px;
line-height: 22px;
}
여기까지는 도구가 알려 준 값을 성실히 옮긴 것입니다. 숫자 하나하나가 인스펙트 패널의 한 줄과 짝을 이룹니다.
66.2 절대 좌표는 관계로 다시 씁니다
도구가 자동으로 뽑아 주는 코드는 흔히 요소를 절대 위치로 박아 둡니다. 그대로 붙이면 화면이 조금만 달라져도 무너지니, 나쁜 예로 두고 고쳐야 합니다.
.item-1 {
position: absolute;
left: 20px;
top: 16px;
}
.item-2 {
position: absolute;
left: 20px;
top: 72px;
}
좌표를 손으로 계산해 박아 두었으니, 위 요소의 높이가 바뀌면 아래가 겹칩니다. 좌표가 아니라 요소 사이의 간격이라는 관계로 다시 씁니다.
.list {
display: flex;
flex-direction: column;
gap: 16px;
padding: 16px 20px;
}
이제 각 항목은 자기 위치를 모릅니다. 부모가 세로로 쌓고 16px 간격만 지키니, 항목이 늘거나 높이가 바뀌어도 알아서 자리를 잡습니다. 인스펙트가 알려 준 72와 16 같은 좌표 대신, 그 차이가 뜻하던 간격만 남깁니다.
66.3 반복되는 값은 토큰 참조로
인스펙트에서 읽은 색과 간격을 화면마다 날값으로 붙이면 금세 흩어집니다. 같은 값이 두 번 이상 보이면 토큰으로 정리해 참조하게 바꿉니다.
.btn {
background: #2563eb;
padding: 10px 16px;
}
.badge {
background: #2563eb;
padding: 4px 8px;
}
같은 파랑이 두 곳에 박혀 있습니다. 토큰으로 올려 두고 두 규칙이 그 이름을 바라보게 합니다.
:root {
--color-primary: #2563eb;
--space-2: 8px;
--space-3: 16px;
}
.btn {
background: var(--color-primary);
padding: 10px var(--space-3);
}
.badge {
background: var(--color-primary);
padding: 4px var(--space-2);
}
인스펙트가 준 값은 그대로지만, 이제 색을 바꾸면 한 곳만 고치면 됩니다. 붙여넣기와 정리하기의 차이가 여기서 갈립니다.
66.4 폰트 값은 통째로 옮깁니다
인스펙트의 타이포 항목은 크기, 두께, 행간, 자간을 한꺼번에 보여 줍니다. 빠뜨리기 쉬운 행간과 자간까지 함께 옮겨야 도구에서 보던 모습이 그대로 재현됩니다.
.title {
font-family: "Pretendard", sans-serif;
font-size: 24px;
font-weight: 700;
line-height: 32px;
letter-spacing: -0.02em;
}
행간을 32px로 정확히 맞춰야 제목 아래 여백이 도구와 어긋나지 않습니다. 크기만 옮기고 행간을 잊으면 미묘하게 뜬 느낌이 남습니다.
66.5 상태 값도 함께 받습니다
핸드오프에서 자주 빠지는 것이 상태입니다. 인스펙트에는 평소 모습만 보여도, hover와 disabled 값을 함께 넘겨받아 규칙으로 적어 두어야 화면이 살아 움직입니다.
.btn {
background: var(--color-primary);
transition: background 0.15s;
}
.btn:hover {
background: #1d4ed8;
}
.btn:disabled {
opacity: 0.5;
cursor: not-allowed;
}
평소 모습만 옮긴 화면은 눌러도 반응이 없어 죽어 있는 느낌을 줍니다. 상태 값까지 받아 적어야 인스펙트 너머의 실제 사용 흐름이 완성됩니다.
66.6 반응형은 고정 폭 대신 유연하게
인스펙트는 특정 폭에서의 값을 보여 주니, 그 폭을 그대로 박으면 좁은 화면에서 넘칩니다. 고정 폭을 최대 폭으로 풀어 유연하게 받습니다.
.card {
width: 320px;
}
디자인이 320px였다고 폭을 못 박으면 작은 화면에서 가로 스크롤이 생깁니다. 최대치만 정하고 그 안에서 줄어들게 바꿉니다.
.card {
width: 100%;
max-width: 320px;
}
넓은 화면에서는 320px를 지키고 좁아지면 함께 줄어듭니다. 인스펙트의 숫자를 상한으로 읽는 감각이 반응형 핸드오프의 핵심입니다.
66.7 그림자와 테두리 값도 정확히
인스펙트의 이펙트 항목에는 그림자의 번짐과 색, 투명도가 담겨 있습니다. 이 값들을 반올림하지 말고 그대로 옮겨야 도구에서 보던 깊이감이 유지됩니다.
.card {
border: 1px solid #e5e7eb;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1),
0 1px 2px rgba(0, 0, 0, 0.06);
}
그림자가 두 겹으로 쌓여 있으면 두 겹을 모두 적습니다. 한 겹만 옮기면 얕아 보이고, 투명도를 0.1에서 0.2로 어림하면 무거워 보입니다. 이런 값도 자주 쓰면 토큰으로 올려 둡니다.
:root {
--shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.1);
--border-subtle: #e5e7eb;
}
.card {
border: 1px solid var(--border-subtle);
box-shadow: var(--shadow-sm);
}
그림자와 경계선도 색이나 간격과 똑같이 이름을 얻으면, 다른 카드나 팝업에서 같은 깊이를 손쉽게 재사용할 수 있습니다.
66.8 핸드오프 체크리스트
값을 옮기고 나면 다섯 가지를 훑습니다. 간격이 관계로 서 있는지, 색과 간격이 토큰을 참조하는지, 폰트의 행간과 자간까지 왔는지, hover와 disabled 상태가 있는지, 폭이 유연한지입니다. 이 다섯을 모두 통과한 카드 규칙은 이런 모습이 됩니다.
.card {
width: 100%;
max-width: 320px;
padding: var(--space-3);
background: var(--color-bg);
border: 1px solid var(--border-subtle);
border-radius: var(--radius-md);
box-shadow: var(--shadow-sm);
}
.card__list {
display: flex;
flex-direction: column;
gap: var(--space-2);
}
인스펙트 값이 그대로 박힌 코드가 아니라, 관계와 토큰으로 정리된 코드입니다. 이렇게 옮겨 두면 화면이 살아 움직이고, 어느 폭에서도 무너지지 않으며, 값 하나를 바꿀 때도 한 곳만 손대면 됩니다.