한국어

CSS 컨테이너 쿼리를 마스터하여 진정한 반응형 웹 디자인을 구현하세요. 뷰포트가 아닌 컨테이너 크기에 따라 레이아웃을 조정하여 모든 기기에서 매끄러운 사용자 경험을 제공하는 방법을 배워보세요.

반응형 디자인의 새로운 가능성: CSS 컨테이너 쿼리 완벽 가이드

수년간 반응형 웹 디자인은 주로 미디어 쿼리에 의존하여 웹사이트가 뷰포트의 너비와 높이에 따라 레이아웃과 스타일을 조정할 수 있도록 했습니다. 이 접근 방식은 효과적이지만, 전체 화면 크기와는 독립적으로 적응해야 하는 복잡한 컴포넌트를 다룰 때 때때로 제한적으로 느껴질 수 있습니다. 이때 등장한 것이 바로 CSS 컨테이너 쿼리입니다 – 이 강력한 새 도구는 요소가 뷰포트 자체가 아닌, 자신을 포함하는 컨테이너 요소의 크기에 반응하도록 합니다. 이는 반응형 디자인에서 새로운 차원의 유연성과 정밀성을 열어줍니다.

CSS 컨테이너 쿼리란 무엇인가?

CSS 컨테이너 쿼리는 부모 컨테이너의 크기나 다른 특성에 따라 요소에 스타일을 적용할 수 있게 해주는 CSS 기능입니다. 뷰포트를 대상으로 하는 미디어 쿼리와 달리, 컨테이너 쿼리는 특정 요소를 대상으로 합니다. 이 덕분에 화면 크기에 상관없이 컴포넌트가 컨테이너 내에서 사용 가능한 공간에 따라 스타일을 조정하는 것이 가능해집니다.

좁은 사이드바에 배치될 때와 넓은 메인 콘텐츠 영역에 배치될 때 다르게 표시되는 카드 컴포넌트를 상상해 보세요. 미디어 쿼리를 사용하면 화면 크기에 따라 카드의 스타일을 조정해야 하므로 일관성이 떨어질 수 있습니다. 컨테이너 쿼리를 사용하면 카드의 컨테이너가 특정 너비에 도달했을 때 특별히 적용되는 스타일을 정의할 수 있어, 다양한 레이아웃에서 일관되고 반응적인 경험을 보장할 수 있습니다.

왜 컨테이너 쿼리를 사용해야 하는가?

컨테이너 쿼리는 기존의 미디어 쿼리에 비해 여러 가지 이점을 제공합니다:

CSS 컨테이너 쿼리 구현 방법

CSS 컨테이너 쿼리를 구현하는 것은 두 가지 핵심 단계, 즉 컨테이너 정의와 쿼리 작성으로 이루어집니다.

1. 컨테이너 정의하기

먼저, 요소를 *컨테이너*로 지정해야 합니다. 이는 container-type 속성을 사용하여 수행됩니다. container-type에는 두 가지 주요 값이 있습니다:

또한 container-name을 사용하여 컨테이너에 이름을 지정할 수 있으며, 이는 쿼리에서 특정 컨테이너를 대상으로 할 때 유용할 수 있습니다. 예를 들면 다음과 같습니다:

.card-container {
  container-type: inline-size;
  container-name: cardContainer;
}

이 코드는 .card-container 클래스를 가진 요소를 컨테이너로 선언합니다. 컨테이너의 너비를 기반으로 쿼리를 허용하기 위해 inline-size를 지정하고 있습니다. 또한 cardContainer라는 이름도 부여했습니다.

2. 컨테이너 쿼리 작성하기

컨테이너를 정의했다면, @container at-rule을 사용하여 컨테이너 쿼리를 작성할 수 있습니다. 구문은 미디어 쿼리와 유사합니다:

@container cardContainer (min-width: 400px) {
  .card {
    flex-direction: row;
  }
  .card-image {
    width: 40%;
  }
  .card-content {
    width: 60%;
  }
}

이 쿼리는 cardContainer라는 이름의 컨테이너의 최소 너비가 400px일 때만 중괄호 안의 스타일을 적용합니다. 이는 (아마도 .card-container의 자식 요소인) .card 요소를 대상으로 하여 레이아웃을 조정합니다. 컨테이너가 400px보다 좁으면 이 스타일들은 적용되지 않습니다.

단축형: 컨테이너 이름을 지정할 필요가 없을 때는 @container 규칙의 단축 버전을 사용할 수도 있습니다:

@container (min-width: 400px) {
  /* Styles to apply when the container is at least 400px wide */
}

컨테이너 쿼리의 실제 예제

컨테이너 쿼리를 사용하여 더 반응적이고 적응성 있는 레이아웃을 만드는 몇 가지 실제 예제를 살펴보겠습니다.

예제 1: 카드 컴포넌트

이 예제는 컨테이너의 너비에 따라 카드 컴포넌트를 조정하는 방법을 보여줍니다. 카드는 컨테이너가 좁을 때는 콘텐츠를 단일 열로, 컨테이너가 더 넓을 때는 두 개의 열로 표시합니다.

HTML:

Card Image

Card Title

This is some sample content for the card.

Learn More

CSS:

.card-container {
  container-type: inline-size;
  border: 1px solid #ccc;
  margin-bottom: 20px;
}

.card {
  display: flex;
  flex-direction: column;
}

.card-image {
  width: 100%;
  height: auto;
}

.card-content {
  padding: 10px;
}

@container (min-width: 500px) {
  .card {
    flex-direction: row;
  }
  .card-image {
    width: 40%;
  }
  .card-content {
    width: 60%;
  }
}

이 예제에서 .card-container는 컨테이너로 선언됩니다. 컨테이너의 너비가 500px 미만일 때, .card는 열 레이아웃을 사용하여 이미지와 콘텐츠를 수직으로 쌓습니다. 컨테이너의 너비가 500px 이상일 때, .card는 행 레이아웃으로 전환되어 이미지와 콘텐츠를 나란히 표시합니다.

예제 2: 내비게이션 메뉴

이 예제는 사용 가능한 공간에 따라 내비게이션 메뉴를 조정하는 방법을 보여줍니다. 컨테이너가 좁을 때는 메뉴 항목이 드롭다운으로 표시됩니다. 컨테이너가 더 넓을 때는 메뉴 항목이 수평으로 표시됩니다.

HTML:


CSS:

.nav-container {
  container-type: inline-size;
  background-color: #f0f0f0;
  padding: 10px;
}

.nav-container ul {
  list-style: none;
  margin: 0;
  padding: 0;
}

.nav-container li {
  margin-bottom: 5px;
}

.nav-container a {
  display: block;
  padding: 5px 10px;
  text-decoration: none;
  color: #333;
}

@container (min-width: 600px) {
  .nav-container ul {
    display: flex;
  }

  .nav-container li {
    margin-right: 10px;
    margin-bottom: 0;
  }

  .nav-container a {
    display: inline-block;
  }
}

이 예제에서 .nav-container는 컨테이너로 선언됩니다. 컨테이너의 너비가 600px 미만일 때, 메뉴 항목은 수직 목록으로 표시됩니다. 컨테이너의 너비가 600px 이상일 때, 메뉴 항목은 flexbox를 사용하여 수평으로 표시됩니다.

예제 3: 상품 목록

전자상거래 상품 목록은 컨테이너의 너비에 따라 레이아웃을 조정할 수 있습니다. 작은 컨테이너에서는 상품 이미지, 제목, 가격이 있는 간단한 목록이 잘 작동할 수 있습니다. 컨테이너가 커짐에 따라 짧은 설명이나 고객 평점과 같은 추가 정보를 추가하여 표현을 향상시킬 수 있습니다. 이는 또한 뷰포트만을 대상으로 하는 것보다 더 세분화된 제어를 가능하게 합니다.

HTML:

Product 1

Product Name 1

$19.99

Product 2

Product Name 2

$24.99

CSS:

.product-listing-container {
  container-type: inline-size;
  display: flex;
  flex-wrap: wrap;
}

.product-item {
  width: 100%;
  margin-bottom: 20px;
  border: 1px solid #eee;
  padding: 10px;
}

.product-item img {
  width: 100%;
  height: auto;
  margin-bottom: 10px;
}

.product-item h3 {
  margin-top: 0;
  font-size: 1.2em;
}

.product-item .price {
  font-weight: bold;
  color: #007bff;
}

@container (min-width: 400px) {
  .product-item {
    width: 50%;
    padding: 15px;
  }
}

@container (min-width: 768px) {
  .product-item {
    width: 33.33%;
  }
}

이 CSS 코드는 먼저 `product-listing-container`를 컨테이너로 설정합니다. 좁은 컨테이너(400px 미만)의 경우, 각 상품 아이템은 너비의 100%를 차지합니다. 컨테이너가 400px를 초과하면 상품 아이템은 두 개의 열로 배열됩니다. 768px를 초과하면 상품 아이템은 세 개의 열로 표시됩니다.

브라우저 지원 및 폴리필

컨테이너 쿼리는 Chrome, Firefox, Safari, Edge를 포함한 최신 브라우저에서 잘 지원됩니다. 그러나 구형 브라우저는 기본적으로 지원하지 않을 수 있습니다.

구형 브라우저를 지원하기 위해 폴리필(polyfill)을 사용할 수 있습니다. 인기 있는 옵션은 npm과 GitHub에서 찾을 수 있는 container-query-polyfill입니다. 폴리필은 지원되지 않는 기능의 격차를 메워주어 구형 브라우저에서도 컨테이너 쿼리를 사용할 수 있게 해줍니다.

컨테이너 쿼리 사용을 위한 모범 사례

컨테이너 쿼리를 사용할 때 염두에 두어야 할 몇 가지 모범 사례는 다음과 같습니다:

일반적인 함정과 이를 피하는 방법

컨테이너 쿼리 vs. 미디어 쿼리: 올바른 도구 선택하기

컨테이너 쿼리는 상당한 이점을 제공하지만, 미디어 쿼리도 여전히 반응형 디자인에서 제 역할을 합니다. 다음은 다양한 상황에 어떤 도구가 가장 적합한지 결정하는 데 도움이 되는 비교입니다:

기능 컨테이너 쿼리 미디어 쿼리
대상 컨테이너 크기 뷰포트 크기
반응성 컴포넌트 기반 페이지 기반
유연성 높음 중간
코드 중복 낮음 높음
사용 사례 재사용 가능한 컴포넌트, 복잡한 레이아웃 전역 레이아웃 조정, 기본 반응성

일반적으로, 컴포넌트의 스타일을 컨테이너 크기에 따라 조정해야 할 때는 컨테이너 쿼리를 사용하고, 뷰포트 크기에 따라 전역적인 레이아웃 조정을 해야 할 때는 미디어 쿼리를 사용하세요. 종종 두 기술을 조합하는 것이 최상의 접근 방식입니다.

컨테이너 쿼리와 함께하는 반응형 디자인의 미래

컨테이너 쿼리는 반응형 디자인에서 중요한 진전을 나타내며, 요소가 다양한 컨텍스트에 어떻게 적응하는지에 대해 더 큰 유연성과 제어력을 제공합니다. 브라우저 지원이 계속해서 향상됨에 따라, 컨테이너 쿼리는 웹 개발자에게 점점 더 중요한 도구가 될 것입니다. 이는 디자이너와 개발자가 모든 기기와 화면 크기에서 매끄러운 경험을 제공하는 진정으로 적응성 있고 사용자 친화적인 웹사이트를 만들 수 있도록 힘을 실어줍니다.

결론

CSS 컨테이너 쿼리는 반응형 디자인 툴킷에 강력하게 추가된 기능입니다. 요소가 자신을 포함하는 컨테이너의 크기에 반응하도록 함으로써, 진정한 컴포넌트 기반 반응성을 가능하게 하고 웹 디자인에서 새로운 차원의 유연성과 정밀성을 열어줍니다. 컨테이너 쿼리를 효과적으로 구현하고 사용하는 방법을 이해함으로써, 모든 사람에게 더 나은 경험을 제공하는 더 적응성 있고, 유지보수하기 쉬우며, 사용자 친화적인 웹사이트를 만들 수 있습니다.

참고 자료