CSS 컨테이너 쿼리: 진정한 반응형 구성요소
수년 동안 반응형 디자인은 "뷰포트에 맞게 레이아웃을 조정"하는 것을 의미했습니다.
구성 요소 카드 @media (max-width: 768px) 그 사람은 그게 얼마나 넓은지 알아
하지만 그는 자신의 화면에 실제로 사용할 수 있는 공간이 얼마나 되는지 알지 못합니다.
맥락. 해당 카드를 좁은 사이드바에 넣으면 마치 카드가 있는 것처럼 작동합니다.
모바일에서는 화면이 27인치 데스크톱이라도 메인 콘텐츠에 넣어주세요.
컨테이너가 스마트폰보다 좁더라도 데스크톱처럼 작동합니다.
Le CSS 컨테이너 쿼리 이 문제를 근본적으로 해결하세요. 구성요소는 크기에 반응할 수 있습니다. 자신의 컨테이너, 아니 뷰포트의 뛰어난 브라우저 지원2025년 기준 88% (Chrome 105+, Firefox 110+, Safari 16+) 이 기술은 프로덕션 준비가 되어 있습니다.
무엇을 배울 것인가
- 미디어 쿼리와 컨테이너 쿼리의 근본적인 차이점
- 포함 컨텍스트를 정의하는 방법
container-type - 구문
@container쿼리용 - 컨테이너 크기 쿼리: 인라인 크기, 블록 크기
- 컨테이너 스타일 쿼리: 사용자 정의 속성을 기반으로 하는 쿼리
- 계층적 쿼리를 위한 명명된 컨테이너
- 컨테이너 쿼리를 Angular, React 및 Vue에 통합하는 방법
미디어 쿼리의 문제
미디어 쿼리는 뷰포트: 폭 화면, 방향, 색 구성표. 이는 레이아웃과 단순하고 구성 요소는 항상 예측 가능한 너비를 차지합니다. 하지만 디자인에서는 최신 시스템에서는 동일한 구성 요소가 근본적으로 다른 상황에서 재사용됩니다.
- 홈페이지의 제품 카드(데스크톱의 경우 3열)
- '관련 제품' 사이드바에 있는 동일한 카드(좁은 열 1개)
- 전체 화면 모달의 동일한 카드(2열)
- 검색 페이지의 동일한 카드(활성 필터에 따라 다름)
미디어 쿼리를 사용하면 각 사용법의 컨텍스트를 미리 알고 작성해야 합니다. 사례별 CSS 선택기. 컨테이너 쿼리를 사용하면 e 자율성: 사용 가능한 공간에 스스로 적응합니다.
컨테이너 정의
컨테이너 쿼리를 사용하기 위한 첫 번째 단계는 어떤 요소가 컨테이너 쿼리인지 선언하는 것입니다.
질문을 받게 될 "컨테이너"입니다. 재산으로 해결됩니다 container-type:
/* Crea un container che risponde alla larghezza (inline-size) */
.card-wrapper {
container-type: inline-size;
}
/* Crea un container che risponde sia a larghezza che altezza */
.card-wrapper {
container-type: size;
}
/* Dai un nome al container per query gerarchiche */
.card-wrapper {
container-type: inline-size;
container-name: card;
}
/* Shorthand */
.card-wrapper {
container: card / inline-size;
}
일단 아이템이 있으면 container-type, 그의 모든 후손
그들은 사용할 수 있습니다 @container 측정기준을 쿼리합니다.
@container 구문
구문은 미디어 쿼리와 동일하지만 뷰포트를 쿼리하는 대신 포함 컨텍스트를 사용하여 가장 가까운 컨테이너를 쿼리합니다.
.card {
/* Layout default: verticale, compatto */
display: grid;
grid-template-areas:
"image"
"content";
gap: 12px;
}
.card__image {
aspect-ratio: 16 / 9;
object-fit: cover;
border-radius: 8px 8px 0 0;
}
/* Quando il container e largo almeno 400px: layout orizzontale */
@container (min-width: 400px) {
.card {
grid-template-areas: "image content";
grid-template-columns: 200px 1fr;
}
.card__image {
aspect-ratio: 1;
border-radius: 8px 0 0 8px;
}
}
/* Quando il container e largo almeno 600px: layout espanso */
@container (min-width: 600px) {
.card {
grid-template-columns: 280px 1fr;
gap: 24px;
padding: 24px;
}
.card__title {
font-size: 1.5rem;
}
}
/* Range syntax (CSS Level 4) - piu leggibile */
@container (200px <= width <= 400px) {
.card {
/* stile per range specifico */
}
}
명명된 컨테이너: 계층적 쿼리
중첩된 컨테이너가 있는 경우 컨테이너 이름을 지정하여 쿼리할 수 있습니다. 가장 가까운 조상 대신 특정 조상:
<!-- HTML struttura -->
<main class="layout" style="container: layout / inline-size">
<aside class="sidebar" style="container: sidebar / inline-size">
<div class="widget">
<!-- Questo widget puo interrogare sia "sidebar" che "layout" -->
</div>
</aside>
</main>
/* Query sul container "sidebar" (il piu vicino) */
@container sidebar (min-width: 300px) {
.widget { display: flex; }
}
/* Query sul container "layout" (l'antenato nominato) */
@container layout (min-width: 1200px) {
.widget { max-width: 400px; }
}
컨테이너 스타일 쿼리: 숨겨진 기능
크기 쿼리 외에도 컨테이너 쿼리도 지원합니다. 스타일 쿼리: 컨테이너의 CSS 사용자 정의 속성 값을 기반으로 쿼리합니다. Chrome 111+ 및 Safari 17.4+에서 지원되는 이 기능은 가능성을 열어줍니다. 테마 및 구성 요소 변형 측면에서 완전히 새로운 기능입니다.
/* Definisci una custom property sul container */
.card-wrapper {
container-type: style;
/* La variante del componente viene comunicata via custom property */
--card-variant: featured;
}
/* Il componente si adatta alla variante del container */
@container style(--card-variant: featured) {
.card {
border: 2px solid var(--color-accent);
background: var(--color-accent-subtle);
}
.card__badge {
display: block; /* mostra il badge "In evidenza" */
}
}
@container style(--card-variant: compact) {
.card {
padding: 8px;
font-size: 0.875rem;
}
.card__image {
display: none; /* nasconde l'immagine in modalita compatta */
}
}
이 패턴을 사용하면 컨테이너에서 의미론적 컨텍스트를 컨테이너로 전달할 수 있습니다. 추가 CSS 또는 JavaScript 클래스가 없는 구성 요소로 캡슐화를 유지합니다.
컨테이너 측정 단위: cqw, cqh, cqi, cqb
컨테이너 쿼리에는 컨테이너와 관련된 새로운 측정 단위도 제공됩니다.
cqw: 용기 폭의 1%cqh: 컨테이너 높이의 1%cqi: 컨테이너 인라인 크기의 1%(= LTR 레이아웃의 경우 cqw)cqb: 컨테이너 블록 크기(= cqh)의 1%cqmin: cqi와 cqb 중 작은 것cqmax: cqi와 cqb 중 큰 것
/* Tipografia fluida relativa al container */
.card__title {
/* Scala da 16px a 24px in base alla larghezza del container */
font-size: clamp(1rem, 4cqi, 1.5rem);
}
/* Padding proporzionale al container */
.card {
padding: 5cqi;
}
/* Gap che si adatta */
.card__grid {
display: grid;
gap: clamp(8px, 2cqi, 24px);
}
Angular, React 및 Vue의 컨테이너 쿼리
Angular: 컨테이너 인식 구성 요소
/* card.component.scss */
:host {
display: block;
container-type: inline-size;
container-name: card-host;
}
.card {
display: grid;
grid-template-areas: "image" "content";
gap: 12px;
}
@container card-host (min-width: 400px) {
.card {
grid-template-areas: "image content";
grid-template-columns: 180px 1fr;
}
}
// card.component.ts
@Component({
selector: 'app-card',
templateUrl: './card.component.html',
styleUrls: ['./card.component.scss'],
// :host come container - nessun JS necessario per il responsive
host: { class: 'card-container' }
})
export class CardComponent {
@Input() product!: Product;
}
React: 컨테이너 쿼리가 포함된 CSS 모듈
/* card.module.css */
.wrapper {
container-type: inline-size;
container-name: card;
}
.card {
display: grid;
gap: 12px;
}
@container card (min-width: 400px) {
.card {
grid-template-columns: 180px 1fr;
}
}
// Card.tsx
import styles from './card.module.css';
export function Card({ product }: { product: Product }) {
return (
<div className={styles.wrapper}>
<article className={styles.card}>
<img src={product.image} alt={product.name} />
<div>
<h3>{product.name}</h3>
<p>{product.description}</p>
</div>
</article>
</div>
);
}
컨테이너 쿼리와 미디어 쿼리: 언제 무엇을 사용해야 할까요?
| 대본 | 최적의 선택 | 이유 |
|---|---|---|
| 전역 페이지 레이아웃 | 미디어 쿼리 | 레이아웃은 뷰포트에 따라 다릅니다. |
| 재사용 가능한 구성요소 | 컨테이너 쿼리 | 구성요소는 해당 컨텍스트에 맞게 조정되어야 합니다. |
| 디자인 시스템 토큰 | 둘 다 | 중단점용 뷰포트, 변형용 컨테이너 |
| 어두운/밝은 모드 | 미디어 쿼리 | 선호 색상 구성표 및 미디어 기능 |
| 동적 사이드바 | 컨테이너 쿼리 | 콘텐츠가 열린/닫힌 사이드바에 맞습니다. |
| 프린트 스타일링 | 미디어 쿼리 | @media print는 미디어 쿼리입니다. |
패턴 방지: 컨테이너 쿼리의 일반적인 실수
실수 #1: 컨테이너 자체 쿼리
요소 container-type 그는 스스로에게 질문할 수 없다
@container — 수정된 하위 항목이어야 합니다.
컨테이너와 규칙을 정의하지 마세요. @container 같은
선택기.
오류 #2: 컨테이너 유형: 높이가 정의되지 않은 크기
container-type: size 컨테이너의 크기가 필요합니다.
너비와 높이가 모두 정의됩니다. 당신이 사용하는 경우 size 컨테이너에
명시적인 높이 없이 쿼리 height e cqh
예상대로 작동하지 않습니다. 미국 inline-size 대다수의
경우의.
다음 단계
이제 컨테이너 쿼리 덕분에 진정한 반응형 구성 요소를 갖게 되었습니다. 시리즈의 다음 기사에서는 CSS Anchor Positioning API를 살펴봅니다. JavaScript 한 줄 없이 툴팁, 드롭다운 및 팝오버를 구현하려면 다음을 수행하세요. CSS를 개발자가 기다려온 선언적 기능에 더 가깝게 만드는 또 다른 기술 수년 동안.
결론
CSS 컨테이너 쿼리는 빌드 방식을 근본적으로 변화시킵니다. 반응형 구성요소. 각 구성 요소가 수행하는 전역 중단점 시스템 대신 알고 존중해야 하며, 각 구성 요소는 자율적이 되고 자체적으로 적응합니다. 맥락. 이는 더 유지 관리하기 쉬운 코드, 진정으로 구성 가능한 디자인 시스템으로 이어집니다. 수동으로 관리해야 하는 극단적인 경우도 적습니다.
88% 이상의 브라우저 지원으로 컨테이너 쿼리를 배포할 준비가 되었습니다. 오늘 생산. 시작하고 구성 요소를 식별하는 가장 좋은 방법은 여러 상황에서 사용되는 디자인 시스템(일반적으로 카드, 목록 항목, 미디어 객체 — 그리고 이를 점진적으로 새로운 패러다임으로 변환합니다.







