🍰 디저트 아틀리에

표가 메모장이 되는 순간

“아직도 메모장에서 벗어나지 못했어.” 개업 예산 화면을 두고 들은 말입니다. 캡처를 보니 정말 그랬습니다.

개발노트 · 화면 · CSS

이렇게 나오고 있었습니다

자본금₩20,000,000
보증금 · 주거지역-2,500,000
매장 · 소형 매장-2,000,000
장비 · 균형형-4,000,000
인테리어-1,500,000
초기 재료-1,000,000
개업 후 운영자금₩9,000,000

항목과 금액이 공백 하나 없이 붙어 있습니다. 구분선도 없고, 금액이 오른쪽에 맞춰지지도 않습니다. 「메모장 같다」는 표현이 정확했습니다.

처음에는 띄어쓰기를 빠뜨린 줄 알았습니다. 코드를 보니 라벨과 금액은 별개의 요소로 잘 나뉘어 있었습니다. 문제는 글이 아니라 배치였습니다.

휴대폰에서는 표를 «옮겨 담습니다»

이 게임은 넓은 화면에서 개업 예산을 오른쪽 사이드바 카드로 보여 줍니다. 휴대폰에서는 그럴 자리가 없어서, 아래쪽에 요약 바를 두고 누르면 시트가 올라오게 했습니다.

그 시트를 만드는 코드는 이렇게 생겼습니다.

const body = ledger.querySelector(".card-b");
ov.querySelector(".card-sheet-b").appendChild(body);   // 통째로 옮긴다

표 내용을 담은 요소를 통째로 시트 안으로 옮깁니다. DOM을 새로 만들지 않아서 값이 어긋날 일이 없습니다. 여기까지는 좋은 방법입니다.

그런데 스타일이 따라오지 않습니다

표 모양은 전부 이렇게 정의돼 있었습니다.

.ledger .row { display:flex; justify-content:space-between;
               border-bottom:1px dotted … }
.ledger .row span:last-child { font-family:var(--mono) }

전부 .ledger 안에 있을 때만 적용됩니다. 그런데 시트로 옮기는 순간, 그 요소는 .ledger 바깥으로 나갑니다. 계산된 값을 찍어 봤습니다.

속성시트로 옮긴 뒤정상
displayblockflex
justify-contentnormalspace-between
구분선nonedotted
금액 글꼴본문 글꼴고정폭

display:flexblock이 되면 라벨과 금액이 그냥 이어 붙습니다. 띄어쓰기가 빠진 게 아니라, 둘 사이를 벌려 주던 것이 사라진 것입니다.

«위치 고정»과 «표 모양»을 나눴습니다

가장 쉬운 해결은 시트에도 .ledger 클래스를 붙이는 것입니다. 그런데 그 클래스에는 이런 게 딸려 있었습니다.

.ledger { position: sticky; top: 64px }

사이드바 카드가 스크롤을 따라다니게 하는 규칙입니다. 시트 안에서는 필요 없고, 오히려 방해가 됩니다. 한 클래스가 두 가지 일을 하고 있었던 것이 진짜 문제였습니다.

그래서 나눴습니다.

.card.ledger { position: sticky; top: 64px }   ← 옆에 붙는 «카드»만
.ledger .row { display:flex; … }               ← 표 모양은 클래스만 따라감

이제 시트 본문에 ledger를 얹으면 표 모양만 따라오고, 위치 고정은 따라오지 않습니다.

결과

라벨↔금액 간격0px234px (양끝 정렬)
구분선없음점선
합계 윗선없음2px
금액 글꼴본문고정폭 (자릿수 정렬)

남은 생각

DOM을 옮겨 담는 방식은 값이 어긋나지 않아서 좋습니다. 대신 스타일이 «어디에 있느냐»에 묶여 있으면 옮기는 순간 벗겨집니다. 이걸 겪고 나서 규칙을 하나 세웠습니다.

요소를 다른 곳으로 옮길 계획이 있다면, 그 요소의 생김새는 부모의 위치가 아니라 자기 클래스에 붙여 둔다.

그리고 클래스 하나가 «어디에 놓일지»와 «어떻게 생겼는지»를 동시에 정하고 있으면, 언젠가 둘 중 하나만 필요한 날이 옵니다. 그때 나누는 것보다 처음부터 나눠 두는 편이 낫습니다.

이 게임에는 휴대폰에서 카드를 시트로 올리는 화면이 몇 군데 더 있습니다. 같은 함정이 남아 있을 가능성이 커서, 하나씩 확인하고 있습니다.

← 개발노트 목록