왜 지그재그 레이아웃인가?

일반적인 그리드 레이아웃은 모든 아이템이 반듯하게 정렬됩니다. 하지만 때로는 아이템이 마치 폭포수처럼 대각선으로 흐르는 리듬감 있는 레이아웃이 필요할 때가 있습니다. 이런 디자인을 CSS Grid와 transform의 조합으로 깔끔하게 구현할 수 있습니다.

Flexbox로도 비슷한 효과를 낼 수 있지만, flex-direction: column + flex-wrap: wrap 방식은 고정 높이가 필요하고 탭 순서(Tab order)가 깨지는 치명적인 단점이 있습니다. 아이템이 시각적으로는 1→2→3→4로 보여도, 실제 DOM 순서는 세로로 먼저 채워지기 때문에 접근성에 문제가 생깁니다. Grid 접근법은 이 문제를 완전히 회피합니다.

CSS grid zigzag layout with staggered items using transform translateY IT Technology Image

핵심 코드: CSS Grid + translateY(50%) 조합

/* 기본 리셋 및 박스 모델 통일 */
*, *::before, *::after {
  box-sizing: border-box;
}

.wrapper {
  --gap: 16px;               /* 간격을 변수로 관리 */
  --item-height: 100px;      /* 아이템 높이 (하드코딩 필요) */
  display: grid;
  grid-template-columns: 1fr 1fr;  /* 2열 그리드 */
  gap: var(--gap);
  max-width: 800px;
  margin: 0 auto;
  /* 변환된 아이템이 넘치지 않도록 패딩 확보 */
  padding-bottom: calc(var(--item-height) / 2 + var(--gap) / 2);
}

.item {
  height: var(--item-height);
  border: 2px solid;
}

/* 짝수 번째 아이템만 50% + 간격의 절반만큼 아래로 이동 */
.item:nth-child(even of .item) {
  transform: translateY(calc(50% + var(--gap) / 2));
}

💡 셀렉터 팁: .item:nth-of-type(even)도 가능하지만, nth-of-type은 태그명을 기준으로 동작합니다. 만약 .wrapper 안에 div.itemspan.item이 섞여 있다면 의도치 않은 결과가 나올 수 있습니다. :nth-child(even of .item)클래스명으로 정확히 필터링하므로 더 안전합니다.

Developer inspecting CSS transform percentage behavior on browser devtools System Abstract Visual

transform 퍼센트의 비밀: 자기 자신 기준

CSS의 다른 속성(예: width: 50%)은 부모 요소의 크기를 기준으로 합니다. 하지만 transform: translateY(50%)자기 자신의 높이를 기준으로 움직입니다. 아이템 높이가 100px이면 50px만큼 아래로 이동합니다.

이 특성 덕분에 아이템 높이가 달라져도 비율이 유지됩니다. 만약 아이템 높이가 200px이라면 translateY(50%)는 100px 이동하므로, 지그재그 간격이 자동으로 조정됩니다.

🚨 Overflow 문제와 해결법

transform은 시각적 효과일 뿐, 실제 레이아웃에는 영향을 주지 않습니다. 따라서 짝수 아이템이 아래로 이동해도 부모 .wrapper는 원래 위치를 기준으로 높이를 계산하므로, 아이템이 컨테이너 밖으로 삐져나옵니다.

해결책은 padding-bottom을 추가해 미리 공간을 확보하는 것입니다. 패딩 값은 (아이템 높이 / 2) + (gap / 2)로 계산합니다. 이 값은 CSS 변수로 관리하면 유지보수가 쉽습니다.

Final waterfall grid layout with padding-bottom overflow fix Development Concept Image

결론: 지그재그 레이아웃의 핵심 3가지

  1. 2열 CSS Grid가 기본 뼈대를 제공합니다.
  2. translateY(50%) 가 지그재그 효과를 만들고, transform 퍼센트가 자기 자신 기준이라는 점이 핵심입니다.
  3. padding-bottom 으로 overflow를 방지해야 합니다.

한국 개발 생태계에서의 적용 맥락

국내에서는 대시보드, 포트폴리오 사이트, 카드형 UI에서 이런 비대칭 레이아웃이 자주 요청됩니다. 특히 기존 SI 프로젝트에서는 모든 카드가 동일한 크기와 간격으로 배치되는 경우가 많아 디자인적으로 차별화가 필요할 때 유용합니다. 하지만 아이템 높이가 동적이거나 반응형이어야 한다면 이 방법은 한계가 있습니다. 그런 경우에는 aspect-ratio를 활용하거나 JavaScript로 동적 계산을 추가하는 것이 좋습니다.

이 기술의 한계 및 주의사항

  • --item-height를 하드코딩해야 하므로, 콘텐츠에 따라 높이가 변하는 환경에서는 부적합합니다.
  • transform은 GPU 가속을 받지만, 많은 아이템(100개 이상)에서 사용하면 성능에 영향을 줄 수 있습니다.
  • 스크린 리더는 DOM 순서를 따르므로 시각적 순서와 DOM 순서가 다르면 혼란을 줄 수 있습니다. 이 방법은 시각적 순서와 DOM 순서가 일치하므로 안전합니다.

다음 단계 학습 방향

  • CSS container queries를 이용한 반응형 지그재그 레이아웃
  • prefers-reduced-motion을 고려한 진입 애니메이션 추가
  • subgrid를 활용한 더 복잡한 비대칭 그리드 패턴

근거자료: 원문 CSS-Tricks 아티클


함께 보면 좋은 글

본 콘텐츠는 신뢰할 수 있는 출처를 바탕으로 AI 도구를 활용하여 초안이 작성되었으며, 편집자의 검토를 거쳐 발행되었습니다. 전문가의 조언을 대체하지 않습니다.