footer가 화면 바닥에 안 붙는다
이날은 CSS 레이아웃 버그와 5번 싸운 날이다.
footer가 화면 바닥에 안 붙었다.
grid로 잡았는데 대화면에서만 실패했다.
소화면에서는 통과한 줄 알았다가 거짓 PASS였다.
결국 flexbox로 전환해서 해결했다.
교육 플랫폼에서 footer 레이아웃 버그가 있었다.
섹션을 grid로 잡았다.
첫 번째 행은 내용이고 두 번째 행은 footer다.
첫 번째 행이 남은 공간을 다
차지해야 footer가 바닥에 붙는다.
근데 대화면에서 footer 아래에 635픽셀 빈 공간이 생겼다.
footer가 바닥에 안 붙고 중간에 떠 있다.
grid minmax가 안 먹는다
CSS 스펙상 minmax(0,1fr)은 첫 번째 행이 남은 공간을 전부 차지해야 한다.
min이 0이니까, 행이 필요한 만큼 늘어난다.
footer 행은 자기 높이만 차지한다.
이래야 footer가 바닥에 붙는다.
근데 Chrome이 이걸 안 지켰다.
고정 높이랑 중첩 grid랑 임베드 컨텍스트가 합쳐지니까, 첫 번째 행을 min-content로 고정해버렸다.
남은 공간을 흡수하지 않는 거다.
footer 행에 715픽셀이 배당됐다.
footer 엘리먼트는 80픽셀인데. overflow
추가해봤다.안 됐다.
track sizing이 안 바뀐다.
실측으로 확인했다.
소화면에서는 통과한 줄 알았다
더 문제는 검증이었다.
소화면에서는 버그가 안 보였다.
footer 아래에 빈 공간이 없었다.
그래서 “해결됐다”고 판단했다.
근데 대화면에서 같은 페이지를 열어보니 빈 공간이 있었다.
소화면에서는 섹션 높이가 작아서 footer 행이 자기 높이만 차지했다.
빈 공간이 안 생기는 거다.
대화면에서는 섹션 높이가 커져서 빈 공간이 드러난다.
이게 거짓 PASS다.
소화면에서만 검증해서 “해결됐다”고 믿은 거다.
레이아웃 버그는 대화면에서 검증해야 한다.
대화면에서 빈 공간이 가장 크게 드러나니까.
flexbox로 전환
결국 grid를 포기하고 flexbox로 전환했다.
섹션을 flex column으로 만들었다.
내용 영역에 flex
min-height 줬다.footer에 shrink
줬다.flexbox는 이 조합을 신뢰성 있게 존중한다.
내용이 남은 공간을 다
차지하고 footer가 자기 높이만 유지한다.
Chrome이 grid에서는 track sizing을 안 지켰지만 flexbox에서는 비율을 지킨다.
진단 방법
이 버그를 진단하는 결정적 증거를 찾았다.
grid 행 높이를 실측한다.
getComputedStyle으로 행 높이를 읽는다.
footer 행이 footer 엘리먼트 높이보다 크면, grid가 제대로 sizing을 안 한 거다.
이 방법이 확실하다.
“빈 공간이 있나”를 눈으로 보는 것보다 정확하다.
왜냐면 눈으로는 grid 행 경계를 못 본다.
근데 행 높이를 읽으면, footer 행에 715픽셀이 배당됐다는 걸 수치로 확인할 수 있다.
JSONL 충돌 병합
CSS 버그 외에도 깃 충돌 병합에서 일반적인 교훈을 찾았다.
append-only JSONL 파일이 충돌했다.
줄 단위로 diff를 보고 병합하려고 했다.
근데 JSONL은 순서가 의미를 갖는다.
줄 단위 diff는 무의미하다.
올바른 병합은 타임스탬프 기준 합집합이다.
양쪽의 엔트리를 모으고 타임스탬프로 정렬하고 같은 타임스탬프는 중복 제거한다.
이렇게 하면 양쪽이 신뢰 원천인 append-only 로그를 올바르게 병합할 수 있다.
부재도 증거다
마지막으로 하나 더. 확장이 실행됐는지 확인할 때, 부재도 증거라는 걸 배웠다.
fire-and-forget로 실행되는 확장이 있었다.
트리거 조건을 만족하는데 실행 부산물이 전혀 없었다.
clientId도 안 바뀌고 콜백 서버도 없고 로그도 없다.
“조건을 만족하는데 왜 안 되지”라고 생각할 수 있다.
근데 부산물이 없다는 건, 실행 자체가 안 됐다는 증거다.
조건을 만족해도 확장이 로드되지 않으면 실행이 안 된다.
부재도 증거다.
“실행됐을 부산물이 없다”는 “실행이 안 됐다”의 증거가 된다.
“조건이 만족되면 실행된다”는 가정이 틀릴 수 있다.
조건 이전에 로드 자체가 안 됐을 수 있다.
마무리
내가 이날 배운 핵심은 다음과 같다.
이날의 교훈은 세 가지다.
첫째, 레이아웃 버그는 대화면에서 검증해야 한다.
소화면에서 통과하면 거짓 PASS다.
빈 공간은 대화면에서 가장 크게 드러난다.
둘째, grid가 안 되면 flexbox로 가라. grid의 minmax(0,1fr)은 스펙상 맞지만 Chrome이 특정 컨텍스트에서 안 지킨다.
실측으로 track sizing이 안 바뀌면 flexbox로 전환하는 게 빠르다.
셋째, 부재도 증거다.
실행됐을 부산물이 없으면, 실행이 안 된 거다.
조건이 만족되어도 로드가 안 됐을 수 있다.
부재를 “아직 안 봤다”가 아니라 “없다”로 읽어야 한다.