본문으로 건너뛰기
개발 머꼬
개발 노트CSS
hohyeon.dev16

같은 카드 컴포넌트가 사이드바에서만 깨지던 이유 — 미디어 쿼리의 한계

  • #CSS
  • #Engineering Note
  • #Layout

문제 발생

본문 영역에서 잘 보이던 카드 컴포넌트를 사이드바에 그대로 재사용했더니 제목이 세 줄로 접히고 썸네일과 텍스트가 겹쳤습니다. 카드에는 이런 규칙이 걸려 있었습니다.

.card { display: grid; grid-template-columns: 1fr; }

@media (min-width: 700px) {
  .card { grid-template-columns: 200px 1fr; }   /* 썸네일 + 본문 */
}

데스크톱에서 보고 있으니 뷰포트는 1440px입니다. 조건이 참이라 사이드바 안의 폭 260px짜리 카드도 2열 규칙을 받습니다.

원인 분석

미디어 쿼리는 뷰포트를 봅니다. 컴포넌트가 실제로 얼마나 넓은 자리를 받았는지는 전혀 모릅니다. 그래서 "화면이 넓다"와 "이 컴포넌트가 넓다"가 어긋나는 순간 규칙이 틀어집니다. 재사용 가능한 컴포넌트를 만들수록 이 어긋남은 잦아집니다 — 같은 카드가 본문, 사이드바, 모달, 2열 그리드 안에 각각 놓이기 때문입니다.

지금까지의 우회법은 .card--narrow 같은 변형 클래스를 만들어 쓰는 쪽에서 붙여주는 것이었습니다. 동작은 하지만 레이아웃 정보를 컴포넌트 바깥이 알고 있어야 하고, 배치가 바뀔 때마다 클래스를 다시 챙겨야 합니다.

컨테이너 쿼리는 기준을 뷰포트에서 조상 컨테이너로 옮깁니다.

해결 방안

  1. 컨테이너를 선언하고, 그 폭을 기준으로 질의합니다.
.card-slot {
  container-type: inline-size;   /* 이 요소가 질의 대상이 된다 */
}

.card { display: grid; grid-template-columns: 1fr; }

@container (width > 700px) {
  .card { grid-template-columns: 200px 1fr; }
}

이제 사이드바의 슬롯은 260px이므로 조건이 거짓이고, 카드는 배치와 무관하게 스스로 맞는 모양을 고릅니다.

  1. container-type 값을 목적에 맞게 고릅니다.
질의 가능한 것
inline-size인라인 방향(가로) 크기. 대부분 이걸 씁니다
size가로·세로 모두. 블록 크기까지 담아둬야 해서 제약이 큽니다
normal크기 질의 불가. 이름 질의와 스타일 질의만
  1. 컨테이너가 여러 겹이면 이름을 붙입니다. 이름이 없으면 가장 가까운 컨테이너가 선택됩니다.
.layout { container: shell / inline-size; }
.card-slot { container: card / inline-size; }

@container card (width > 700px) { ... }
  1. 컨테이너 상대 단위를 쓸 수 있습니다. cqi는 컨테이너 인라인 크기의 1%입니다. 뷰포트 단위(vw)로는 표현할 수 없던 "이 컴포넌트 폭에 비례하는 글자 크기"가 가능해집니다.
.card h2 { font-size: max(1.5rem, 1.2rem + 2cqi); }
  1. 컨테이너는 자기 자신을 질의할 수 없습니다. @container는 그 컨테이너의 자손에만 적용됩니다. .cardcontainer-type을 걸고 .card를 스타일하려 하면 아무 일도 일어나지 않습니다 — 크기가 스타일에 영향을 주고 그 스타일이 다시 크기를 바꾸는 순환을 막기 위한 규칙입니다. 그래서 감싸는 슬롯 요소가 하나 필요합니다.

공식 문서

마지막 수정

좋아요북마크

댓글0

아직 댓글이 없어요. 첫 의견을 편하게 남겨 보세요.