CSS 유틸리티

[Container Queries] 화면이 아니라 '담긴 칸' 너비로 반응하는 레이아웃

같은 카드가 좁은 칸에선 세로로, 넓은 칸에선 가로로 자동 전환됩니다. 미디어 쿼리(화면 크기 기준) 없이 컴포넌트가 자기가 담긴 칸 너비만 보고 모양을 바꿔요.

CSS Container Queries@containercontainer-typeinline-sizemin-width
라이브 데모
새 탭에서 열기
데모 불러오는 중…

제작 과정

한 줄 요약 - 부모 박스에 container-type 한 줄을 주면, 안쪽 컴포넌트가 화면(viewport)이 아니라 자기가 담긴 칸 너비를 보고 레이아웃을 바꿉니다.

이럴 때 필요해요

똑같은 카드를 넓은 본문에도 쓰고 좁은 사이드바에도 쓰는데, 미디어 쿼리(화면 크기로 반응하는 옛 방식)는 '화면 전체 너비'만 봅니다. 그래서 화면은 큰데 카드가 좁은 칸에 들어가면 가로로 펼쳐져 깨져요. 칸마다 따로 클래스를 붙이는 땜질도 금방 한계가 옵니다. 컨테이너 쿼리는 컴포넌트가 '자기가 들어간 칸'을 기준으로 반응하게 해서 이 문제를 뿌리부터 없앱니다.

어떻게 동작하나

  1. 카드를 감싼 박스에 container-type: inline-size 를 줍니다. 이러면 그 박스가 '크기 기준점'이 됩니다 (inline-size = 가로 너비를 기준으로 삼겠다는 뜻).

  2. 카드 안쪽 스타일에 @container (min-width: 380px) 규칙을 둡니다. 이 규칙은 화면이 아니라 '가장 가까운 기준점 박스'의 너비를 봅니다.

  3. 그 박스가 380px보다 넓어지는 순간 카드가 세로(이미지 위)에서 가로(이미지 왼쪽) 레이아웃으로 바뀝니다. 화면 크기는 전혀 건드리지 않아요.

핵심은 이거예요

반응의 기준이 '화면'에서 '담긴 칸'으로 바뀝니다. 카드 코드는 한 벌뿐이고, 좁게 보일지 넓게 보일지는 카드가 아니라 카드를 감싼 칸이 정합니다. 그래서 같은 컴포넌트를 어디에 놔도 알아서 맞춰져요.

놓치기 쉬운 것

  • @container 규칙은 반드시 container-type을 가진 '부모'가 있어야 동작합니다. 기준점이 없으면 규칙이 무시돼 아무 일도 안 일어나요.

  • 기준점 박스 자신에는 @container가 안 걸립니다. 측정 대상은 항상 그 안쪽 자식이에요. 그래서 보통 래퍼 한 겹을 따로 둡니다.

  • 아주 오래된 브라우저는 미지원이라, 그 경우 기본(좁은) 레이아웃으로 안전하게 보이게 설계하면 깨지지 않습니다.

이런 곳에 써요

  • 대시보드 위젯 - 같은 카드가 1단/2단/넓은 패널 어디에 놓이든 칸 너비에 맞춰 재배치.

  • 상품/게시물 카드 - 본문 그리드에선 가로, 좁은 추천 사이드바에선 세로로 한 컴포넌트가 양쪽 다 커버.

소스 코드

· 데모 페이지에서 자동 추출
import type { Metadata } from "next";
import { ContainerQueriesDemo } from "./-components/ContainerQueriesDemo";

export const metadata: Metadata = {
  title: "CSS Container Queries (데모)",
  description:
    "@container 한 줄이면 컴포넌트가 화면(viewport)이 아니라 자기가 담긴 칸의 너비를 보고 레이아웃을 바꿉니다. 같은 카드가 좁은 칸에선 세로로, 넓은 칸에선 가로로 자동 전환.",
  robots: { index: false, follow: false },
};

export default function Page() {
  return (
    <main className="flex min-h-[100dvh] items-center justify-center bg-white">
      <ContainerQueriesDemo />
    </main>
  );
}
48조회수

댓글