컨테이너 쿼리 사용 방법

최근 크리스 코이어는 다음과 같은 질문을 던지는 블로그 게시물을 작성했습니다.

이제 컨테이너 쿼리는 모든 브라우저 엔진에서 지원되나, 더 많은 개발자가 컨테이너 쿼리를 사용하지 않는 이유는 무엇일까요?

크리스의 게시물에는 여러 가지 잠재적인 이유 (예: 인식 부족, 오래된 습관이 심하게 고장남)가 나와 있지만 두드러진 특별한 이유가 한 가지 있습니다.

일부 개발자는 지금은 컨테이너 쿼리를 사용하고 싶다고 말하지만, 사용할 수 없다고 여전히 이전 브라우저를 지원해야 하기 때문이라고 생각합니다.

제목에서 짐작할 수 있듯 이전 브라우저를 지원해야 하는 경우에도 대부분의 개발자는 현재 프로덕션 단계에서 컨테이너 쿼리를 사용할 수 있다고 생각합니다. 이 게시물에서는 이를 위한 권장 방법을 안내합니다.

실용적인 접근 방식

이제 코드에 컨테이너 쿼리를 사용하고 싶지만 모든 브라우저에서 동일한 경험을 하고 싶다면 컨테이너 쿼리를 지원하지 않는 브라우저에 자바스크립트 기반 대체를 구현할 수 있습니다.

문제는 '대체는 얼마나 포괄적이어야 하는가?'입니다.

다른 대체와 마찬가지로 유용성과 성능 간에 적절한 균형을 유지하는 것이 과제입니다. CSS 기능의 경우 전체 API를 지원하는 것이 불가능한 경우가 많습니다 (폴리필을 사용하지 않는 이유 참고). 그러나 대부분의 개발자가 사용하기를 원하는 핵심 기능 세트를 파악한 다음 이러한 기능에 대해서만 대체를 최적화할 수 있습니다.

그렇다면 '핵심 기능'이란 무엇일까요? 궁금할 수 있습니다 이 질문에 답하려면 현재 대부분의 개발자가 미디어 쿼리를 사용하여 반응형 사이트를 구축하는 방법을 생각해 보세요.

거의 모든 최신 디자인 시스템과 구성요소 라이브러리는 모바일 우선 원칙에 따라 표준화되었으며 사전 정의된 중단점 세트 (예: SM, MD, LG, XL)를 사용하여 구현되었습니다. 구성요소는 기본적으로 작은 화면에 잘 표시되도록 최적화되어 있으며, 스타일은 고정된 더 큰 화면 너비 집합을 지원하기 위해 조건부로 레이어링됩니다. 이에 관한 예는 부트스트랩Tailwind 문서를 참고하세요.

이 접근 방식은 표시 영역 기반 디자인 시스템과 마찬가지로 컨테이너 기반 디자인 시스템과 마찬가지로 관련이 있습니다. 대부분의 경우 디자이너에게 중요한 것은 화면이나 표시 영역의 크기가 아니라 배치된 컨텍스트에서 구성요소에 사용할 수 있는 공간의 크기이기 때문입니다. 즉, 중단점은 전체 표시 영역을 기준으로 하고 전체 페이지에 적용 가능한 것이 아니라 사이드바, 모달 대화상자 또는 게시물 본문과 같은 특정 콘텐츠 영역에 적용됩니다.

현재 대부분의 개발자가 사용하는 모바일 중심, 중단점 기반 접근 방식의 제약 조건 내에서 작업할 수 있다면 모든 단일 컨테이너 쿼리 기능을 완벽하게 지원하는 것보다 해당 접근 방식에 컨테이너 기반 대체를 구현하는 것이 훨씬 쉽습니다.

다음 섹션에서는 이 모든 것이 어떻게 작동하는지, 기존 사이트에 이를 구현하는 방법을 단계별로 설명합니다.

작동 방식

1단계: @media 규칙 대신 @container 규칙을 사용하도록 구성요소 스타일 업데이트

이 첫 번째 단계에서는 표시 영역을 기반으로 한 크기 조정이 아닌 컨테이너 기반 크기 조정을 사용할 때 도움이 될 것으로 생각되는 사이트의 구성요소를 식별합니다.

먼저 한두 개의 구성요소로 시작하여 이 전략의 작동 방식을 확인하는 것이 좋지만 구성요소의 100% 를 컨테이너 기반 스타일 지정으로 변환하려는 경우에도 괜찮습니다. 이 전략의 장점은 필요한 경우 점진적으로 채택할 수 있다는 것입니다.

업데이트할 구성요소를 식별한 후에는 해당 구성요소의 각 @media 규칙을 변경해야 합니다. CSS를 @container 규칙에 추가합니다.

다음은 .photo-gallery 구성요소 (기본적으로 단일 열)에서 표시되고 @media 규칙을 사용하여 레이아웃을 업데이트하여 MD 및 XL 중단점에서 각각 2개 또는 3개의 열이 되도록 이를 보여주는 예입니다.

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

/* Styles for the `MD` breakpoint */
@media (min-width: 800px) {
  .photo-gallery {
    grid-template-columns: 1fr 1fr;
  }
}

/* Styles for the `XL` breakpoint */
@media (min-width: 1200px) {
  .photo-gallery {
    grid-template-columns: 1fr 1fr 1fr;
  }
}

@container 규칙을 사용하도록 .photo-gallery 구성요소를 업데이트하려면 먼저 CSS에서 @media 문자열을 @container 문자열로 바꿉니다. 두 규칙의 문법은 매우 비슷하므로 대부분의 경우 이것만으로도 변경할 수 있습니다.

사이트의 디자인에 따라 크기 조건을 업데이트해야 할 수도 있습니다. 특히 사이트의 @media 규칙에서 다양한 표시 영역 크기에서 특정 구성요소가 사용할 수 있는 공간의 크기를 특정하게 하는 경우 더욱 그렇습니다.

예를 들어 이전 예에서 MDXL 중단점의 .photo-gallery CSS 스타일이 이러한 중단점에 200픽셀 너비의 사이드바가 표시된다고 가정한다면 @container 규칙의 크기 조건은 약 200픽셀 더 작아야 합니다. 즉, '컨테이너'가 .photo-gallery 구성요소의 요소에는 사이드바가 포함되지 않습니다.

.photo-gallery CSS를 @media 규칙에서 @container 규칙으로 변환하기 위한 전체 변경사항은 다음과 같습니다.

/* Before, using the original breakpoint sizes: */
@media (min-width: 800px) { /* ... */ }
@media (min-width: 1200px) { /* ... */ }

/* After, with the breakpoint sizes reduced by 200px: */
@container (min-width: 600px) { /* ... */ }
@container (min-width: 1000px) { /* ... */ }

선언 블록 내의 스타일은 변경할 필요가 없습니다. 특정 스타일이 적용되어야 하는 시점이 아닌 구성요소의 어떻게 표시되는지를 반영하기 때문입니다.

구성요소 스타일을 @media 규칙에서 @container 규칙으로 업데이트했다면 다음 단계는 컨테이너 요소를 구성하는 것입니다.

2단계: HTML에 컨테이너 요소 추가

이전 단계에서 컨테이너 요소의 크기를 기반으로 구성요소 스타일을 정의했습니다. 다음 단계는 페이지에서 어떤 요소가 @container 규칙의 크기를 기준으로 하는 컨테이너 요소여야 하는지 정의하는 것입니다.

container-type 속성을 size 또는 inline-size로 설정하여 CSS에서 모든 요소를 컨테이너 요소로 선언할 수 있습니다. 컨테이너 규칙이 너비 기반이면 일반적으로 inline-size를 사용하게 됩니다.

다음과 같은 기본 HTML 구조의 사이트를 생각해 보세요.

<body>
  <div class="sidebar">...</div>
  <div class="content">...</div>
</body>

이 사이트 컨테이너.sidebar.content 요소를 만들려면 CSS에 다음 규칙을 추가하세요.

.content, .sidebar {
  container-type: inline-size;
}

컨테이너 쿼리를 지원하는 브라우저의 경우 이 CSS만 있으면 이전 단계에서 정의한 구성요소 스타일을 기본 콘텐츠 영역 또는 사이드바를 기준으로 만들 수 있습니다. 이때 요소가 어떤 요소에 있는지에 따라 달라집니다.

그러나 컨테이너 쿼리를 지원하지 않는 브라우저의 경우 몇 가지 추가 작업이 필요합니다.

컨테이너 요소의 크기가 변경되는 시점을 감지하는 코드를 추가한 다음 이러한 변경사항에 따라 CSS가 연결할 수 있는 방식으로 DOM을 업데이트해야 합니다.

다행히 이를 위해 필요한 코드는 최소한의 코드이며, 모든 사이트와 콘텐츠 영역에서 사용할 수 있는 공유 구성요소로 완전히 추상화할 수 있습니다.

다음 코드는 크기 변경을 자동으로 수신 대기하고 CSS에서 스타일을 지정할 수 있는 중단점 클래스를 추가하는 재사용 가능한 <responsive-container> 요소를 정의합니다.

// A mapping of default breakpoint class names and min-width sizes.
// Redefine these (or add more) as needed based on your site's design.
const defaultBreakpoints = {SM: 400, MD: 600 LG: 800, XL: 1000};

// A resize observer that monitors size changes to all <responsive-container>
// elements and calls their `updateBreakpoints()` method with the updated size.
const ro = new ResizeObserver((entries) => {
  entries.forEach((e) => e.target.updateBreakpoints(e.contentRect));
});

class ResponsiveContainer extends HTMLElement {
  connectedCallback() {
    const bps = this.getAttribute('breakpoints');
    this.breakpoints = bps ? JSON.parse(bps) : defaultBreakpoints;
    this.name = this.getAttribute('name') || '';
    ro.observe(this);
  }
  disconnectedCallback() {
    ro.unobserve(this);
  }
  updateBreakpoints(contentRect) {
    for (const bp of Object.keys(this.breakpoints)) {
      const minWidth = this.breakpoints[bp];
      const className = this.name ? `${this.name}-${bp}` : bp;
      this.classList.toggle(className, contentRect.width >= minWidth);
    }
  }
}

self.customElements.define('responsive-container', ResponsiveContainer);
드림 <ph type="x-smartling-placeholder">

이 코드는 DOM의 <responsive-container> 요소에 관한 크기 변경을 자동으로 수신 대기하는 ResizeObserver을 만들어 작동합니다. 크기 변경이 정의된 중단점 크기 중 하나와 일치하면 해당 중단점 이름을 가진 클래스가 요소에 추가됩니다 (조건이 더 이상 일치하지 않으면 삭제됨).

예를 들어 <responsive-container> 요소의 width가 600~800픽셀 (코드에 설정된 기본 중단점 값에 따름)이면 다음과 같이 SMMD 클래스가 추가됩니다.

<responsive-container class="SM MD">...</responsive-container>

이러한 클래스를 사용하면 컨테이너 쿼리를 지원하지 않는 브라우저의 대체 스타일을 정의할 수 있습니다 (3단계: CSS에 대체 스타일 추가 참고).

이 컨테이너 요소를 사용하도록 이전 HTML 코드를 업데이트하려면 사이드바와 기본 콘텐츠 <div> 요소를 <responsive-container> 요소로 변경하세요.

<body>
  <responsive-container class="sidebar">...</responsive-container>
  <responsive-container class="content">...</responsive-container>
</body>

대부분의 경우 맞춤설정 없이 <responsive-container> 요소만 사용할 수 있지만 맞춤설정해야 하는 경우 다음 옵션을 사용할 수 있습니다.

  • 맞춤 중단점 크기: 이 코드는 기본 중단점 클래스 이름과 최소 너비 크기 집합을 사용하지만 이러한 기본값을 원하는 대로 변경합니다. breakpoints 속성을 사용하여 요소별로 이러한 값을 재정의할 수도 있습니다.
  • 이름이 지정된 컨테이너: 이 코드는 name 속성을 전달하여 이름이 지정된 컨테이너도 지원합니다. 이는 컨테이너 요소를 중첩해야 하는 경우 중요할 수 있습니다. 자세한 내용은 제한사항 섹션을 참고하세요.

다음은 이러한 두 구성 옵션을 설정하는 예입니다.

<responsive-container
  name='sidebar'
  breakpoints='{"bp4":400,"bp5":500,"bp6":600,"bp7":700,"bp8":800,"bp9":900,"bp10":1000}'>
</responsive-container>

마지막으로 이 코드를 번들로 묶을 때는 브라우저에서 컨테이너 쿼리를 지원하지 않는 경우에만 기능 감지 및 동적 import()를 사용하여 로드해야 합니다.

if (!CSS.supports('container-type: inline-size')) {
  import('./path/to/responsive-container.js');
}

3단계: CSS에 대체 스타일 추가

이 전략의 마지막 단계는 @container 규칙에 정의된 스타일을 인식하지 못하는 브라우저를 위한 대체 스타일을 추가하는 것입니다. <responsive-container> 요소에 설정된 중단점 클래스를 사용하여 규칙을 복제하면 됩니다.

이전의 .photo-gallery 예를 계속 살펴보면 두 @container 규칙의 대체 스타일은 다음과 같을 수 있습니다.

/* Container query styles for the `MD` breakpoint. */
@container (min-width: 600px) {
  .photo-gallery {
    grid-template-columns: 1fr 1fr;
  }
}

/* Fallback styles for the `MD` breakpoint. */
@supports not (container-type: inline-size) {
  :where(responsive-container.MD) .photo-gallery {
    grid-template-columns: 1fr 1fr;
  }
}

/* Container query styles for the `XL` breakpoint. */
@container (min-width: 1000px) {
  .photo-gallery {
    grid-template-columns: 1fr 1fr 1fr;
  }
}

/* Fallback styles for the `XL` breakpoint. */
@supports not (container-type: inline-size) {
  :where(responsive-container.XL) .photo-gallery {
    grid-template-columns: 1fr 1fr 1fr;
  }
}

이 코드에는 각 @container 규칙에 상응하는 중단점 클래스가 있는 경우 <responsive-container> 요소와 조건부로 일치하는 동일한 규칙이 있습니다.

<responsive-container> 요소와 일치하는 선택기 부분은 :where() 기능적 의사 클래스 선택기로 래핑되므로 대체 선택기의 특수성이 @container 규칙 내에 있는 원래 선택기의 특이성과 같아집니다.

또한 각 대체 규칙은 @supports 선언에 래핑됩니다. 이는 대체가 작동하는 데 반드시 필요하지는 않지만 컨테이너 쿼리를 지원한다면 브라우저가 이러한 규칙을 완전히 무시하므로 일반적으로 스타일 일치 성능을 개선할 수 있습니다. 또한 브라우저가 컨테이너 쿼리를 지원하고 이러한 대체 스타일이 필요하지 않다는 것을 알고 있는 경우 빌드 도구나 CDN이 이러한 선언을 제거할 수도 있습니다.

이 대체 전략의 주요 단점은 스타일 선언을 두 번 반복해야 하므로 지루하고 오류가 발생하기 쉽습니다. 그러나 CSS 전처리기를 사용하는 경우 @container 규칙과 대체 코드를 모두 생성하는 믹스인으로 이를 추상화할 수 있습니다. 다음은 Sass를 사용하는 예입니다.

@use 'sass:map';

$breakpoints: (
  'SM': 400px,
  'MD': 600px,
  'LG': 800px,
  'XL': 1000px,
);

@mixin breakpoint($breakpoint) {
  @container (min-width: #{map.get($breakpoints, $breakpoint)}) {
    @content();
  }
  @supports not (container-type: inline-size) {
    :where(responsive-container.#{$breakpoint}) & {
      @content();
    }
  }
}

그런 다음 이 믹스인을 만든 후에는 원래 .photo-gallery 구성요소 스타일을 다음과 같이 업데이트할 수 있습니다. 그러면 중복이 완전히 제거됩니다.

.photo-gallery {
  display: grid;
  grid-template-columns: 1fr;

  @include breakpoint('MD') {
    grid-template-columns: 1fr 1fr;
  }

  @include breakpoint('XL') {
    grid-template-columns: 1fr 1fr 1fr;
  }
}

수행할 작업은 이것뿐입니다.

요약

요약하자면, 교차 브라우저 대체로 컨테이너 쿼리를 사용하도록 코드를 업데이트하는 방법은 다음과 같습니다.

  1. 컨테이너를 기준으로 스타일을 지정할 구성요소를 식별하고 @container 규칙을 사용하도록 CSS에서 @media 규칙을 업데이트합니다. 또한 컨테이너 규칙의 크기 조건과 일치하도록 일련의 중단점 이름을 표준화합니다.
  2. 맞춤 <responsive-container> 요소를 구동하는 JavaScript를 추가한 다음 구성요소를 기준으로 삼을 페이지의 콘텐츠 영역에 <responsive-container> 요소를 추가합니다.
  3. 이전 브라우저를 지원하려면 HTML의 <responsive-container> 요소에 자동으로 추가되는 중단점 클래스와 일치하는 대체 스타일을 CSS에 추가합니다. CSS 전처리기 믹스인을 사용하면 동일한 스타일을 두 번 작성할 필요가 없습니다.

이 전략의 장점은 일회성 설정 비용이 있다는 것입니다. 하지만 그 이후에는 새 구성요소를 추가하고 컨테이너 관련 스타일을 정의하는 작업을 별도로 하지 않아도 됩니다.

실제 사례 보기

이러한 모든 단계가 결합되는 방식을 이해하는 가장 좋은 방법은 실제 데모를 보는 것입니다.

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder"></ph> <ph type="x-smartling-placeholder">
컨테이너 쿼리 데모 사이트와 상호작용하는 사용자의 동영상 사용자가 포함하는 콘텐츠 영역의 크기에 따라 구성요소 스타일이 업데이트되는 방식을 표시하기 위해 콘텐츠 영역의 크기를 조절합니다.

이 데모는 2019년에 만들어진 사이트 (컨테이너 쿼리가 존재하기 전)의 업데이트 버전으로, 진정한 반응형 구성요소 라이브러리를 빌드하는 데 컨테이너 쿼리가 필수인 이유를 설명하는 데 도움이 됩니다.

이 사이트에는 이미 다양한 '반응형 구성요소'에 대한 스타일이 정의되어 있었기 때문에 여기에 소개된 전략을 중요한 사이트에서 테스트하기에 완벽했습니다. 실제로 업데이트가 매우 간단했고 기존 사이트 스타일을 거의 변경할 필요가 없었습니다.

GitHub에서 전체 데모 소스 코드를 확인하고 특히 데모 구성요소 CSS를 확인하여 대체 스타일이 정의되는 방식을 알아보세요. 대체 동작만 테스트하려면 컨테이너 쿼리를 지원하는 브라우저에서도 해당 변형만 포함하는 대체 전용 데모를 참조하세요.

한계 및 잠재적인 개선

이 게시물의 시작 부분에서 언급했듯이, 여기서 설명하는 전략은 개발자가 컨테이너 쿼리에 도달할 때 실제로 관심을 두는 대부분의 사용 사례에 효과적입니다.

하지만 이 전략에서 의도적으로 지원을 시도하지 않는 고급 사용 사례가 몇 가지 있습니다. 이 사례는 다음에 다루겠습니다.

컨테이너 쿼리 단위

컨테이너 쿼리의 사양은 컨테이너의 크기를 기준으로 한 새 단위의 수를 정의합니다. 상황에 따라 유용할 수도 있지만 대부분의 반응형 디자인은 비율이나 그리드 또는 플렉스 레이아웃과 같은 기존 수단을 통해 구현할 수 있습니다.

즉, 컨테이너 쿼리 단위를 사용해야 하는 경우 커스텀 속성을 사용하여 컨테이너 쿼리 단위를 쉽게 지원할 수 있습니다. 특히 다음과 같이 컨테이너 요소에 사용되는 각 단위에 대한 맞춤 속성을 정의합니다.

responsive-container {
  --cqw: 1cqw;
  --cqh: 1cqh;
}

그런 다음 컨테이너 쿼리 단위에 액세스해야 할 때마다 단위 자체를 사용하는 대신 이러한 속성을 사용합니다.

.photo-gallery {
  font-size: calc(10 * var(--cqw));
}

그런 다음 이전 브라우저를 지원하려면 ResizeObserver 콜백 내의 컨테이너 요소에서 이러한 맞춤 속성 값을 설정합니다.

class ResponsiveContainer extends HTMLElement {
  // ...
  updateBreakpoints(contentRect) {
    this.style.setProperty('--cqw', `${contentRect.width / 100}px`);
    this.style.setProperty('--cqh', `${contentRect.height / 100}px`);

    // ...
  }
}

이를 통해 이러한 값을 JavaScript에서 CSS로 변경하면 CSS의 모든 기능 (예: calc(), min(), max(), clamp())을 필요에 따라 조작할 수 있습니다.

논리 속성 및 쓰기 모드 지원

이러한 CSS 예시 중 일부의 @container 선언에 width 대신 inline-size가 사용된 것을 확인할 수 있습니다. 또한 새로운 cqicqb 단위 (각각 인라인 및 블록 크기용)도 확인하셨을 것입니다. 이러한 새로운 기능은 CSS가 물리적 또는 방향적 속성이 아닌 논리적 속성 및 값으로 전환했음을 반영합니다.

불행히도 크기 조절 관찰자와 같은 API는 여전히 widthheight의 값을 보고하므로 디자인에 논리적 속성의 유연성이 필요한 경우 직접 알아내야 합니다.

컨테이너 요소를 전달하는 getComputedStyle()와 같은 것을 사용하여 쓰기 모드를 가져올 수 있지만 그렇게 하면 비용이 발생하며 쓰기 모드가 변경되는지 감지할 수 있는 좋은 방법은 없습니다.

따라서 가장 좋은 접근 방식은 <responsive-container> 요소 자체가 사이트 소유자가 필요에 따라 설정 (및 업데이트)할 수 있는 쓰기 모드 속성을 허용하는 것입니다. 이를 구현하려면 이전 섹션에 표시된 것과 동일한 접근 방식을 따르고 필요에 따라 widthheight를 바꿉니다.

중첩된 컨테이너

container-name 속성을 사용하면 컨테이너에 이름을 지정한 다음 @container 규칙에서 참조할 수 있습니다. 명명된 컨테이너는 컨테이너 내에 중첩된 컨테이너가 있고 가장 가까운 상위 컨테이너뿐만 아니라 특정 컨테이너만 일치시켜야 하는 경우에 유용합니다.

여기에 설명된 대체 전략은 하위 연결자를 사용하여 특정 중단점 클래스와 일치하는 요소의 스타일을 지정합니다. 중첩된 컨테이너가 있으면 여러 컨테이너 요소 상위의 중단점 클래스가 특정 구성요소와 동시에 일치할 수 있으므로 이 오류가 발생할 수 있습니다.

예를 들어 여기에는 .photo-gallery 구성요소를 래핑하는 <responsive-container> 요소가 두 개 있지만 외부 컨테이너가 내부 컨테이너보다 크기 때문에 다른 중단점 클래스가 추가됩니다.

<responsive-container class="SM MD LG">
  ...
  <responsive-container class="SM">
    ...
    <div class="photo-gallery">...</div class="photo-gallery">
  </responsive-container>
</responsive-container>

이 예에서 외부 컨테이너의 MDLG 클래스는 .photo-gallery 구성요소와 일치하는 스타일 규칙에 영향을 미칩니다. 이러한 규칙은 가장 가까운 상위 컨테이너와만 일치하므로 컨테이너 쿼리의 동작과 일치하지 않습니다.

이 문제를 해결하려면 다음 중 하나를 수행합니다.

  1. 항상 중첩하는 컨테이너의 이름을 지정한 다음, 충돌을 방지하기 위해 중단점 클래스에 이 컨테이너 이름을 접두사로 붙여야 합니다.
  2. 대체 선택기에서 하위 요소 결합자 대신 하위 조합자를 사용합니다 (약간 더 제한적임).

데모 사이트의 중첩된 컨테이너 섹션에는 명명된 컨테이너를 사용하는 이 예가 포함되어 있습니다. 코드에서 사용하는 Sass 믹스인은 이름이 지정된 규칙과 이름이 지정되지 않은 규칙 모두에 대한 대체 스타일을 생성합니다. @container

:where(), 맞춤 요소 또는 관찰자 크기 조절을 지원하지 않는 브라우저는 어떻게 되나요?

이러한 API는 비교적 새로운 것처럼 보일 수 있지만, 모두 3년 넘게 모든 브라우저에서 지원되었으며 널리 사용되는 Baseline의 일부입니다.

따라서 사이트 방문자의 상당수가 이러한 기능 중 하나를 지원하지 않는 브라우저를 사용하고 있다는 데이터가 없다면 대체 없이 이러한 기능을 자유롭게 사용하지 않을 이유가 없습니다.

이 특정 사용 사례에서도 최악의 경우 사용자 중 극소수의 사용자에게는 대체가 작동하지 않아 컨테이너 크기에 최적화된 뷰가 아닌 기본 뷰가 표시됩니다.

사이트의 기능은 여전히 작동해야 하며 이것이 정말 중요합니다.

그냥 컨테이너 쿼리 폴리필만 사용하면 안 되는 이유는 무엇일까요?

CSS 기능은 폴리필하기가 까다롭기 때문에 일반적으로 브라우저의 전체 CSS 파서와 캐스케이드 로직을 JavaScript로 다시 구현해야 합니다. 따라서 CSS 폴리필 작성자는 거의 항상 수많은 기능 제한과 상당한 성능 오버헤드를 수반하는 많은 절충안을 수행해야 합니다.

따라서 CSS 폴리필은 일반적으로 프로덕션 환경에서 사용하지 않는 것이 좋습니다. 예를 들어 더 이상 유지보수되지 않으며 주로 데모 목적으로 제작된 Chrome 실험실의 container-query-polyfill은 프로덕션 단계에서 사용하지 않는 것이 좋습니다.

여기서 설명하는 대체 전략은 제한사항이 적고 필요한 코드도 훨씬 적으며 어떤 컨테이너 쿼리 폴리필보다도 성능이 훨씬 뛰어납니다.

이전 브라우저에 대한 대체를 구현해야 하나요?

여기에 언급된 제한 사항에 대해 우려되는 점이 있다면 애초에 대체를 실제로 구현해야 하는지 여부를 자문해 보는 것이 좋습니다. 이러한 제한을 피하는 가장 쉬운 방법은 대체 없이 기능을 사용하는 것입니다. 솔직히 많은 경우 이것이 아주 합리적인 선택일 수 있습니다.

caniuse.com에 따르면 전 세계 인터넷 사용자 중 90% 가 컨테이너 쿼리를 지원하고 있으며, 이 게시물을 읽는 많은 사람의 경우 사용자 기반에 비해 컨테이너 쿼리가 더 많을 것으로 보입니다. 따라서 대부분의 사용자가 UI의 컨테이너 쿼리 버전을 보게 된다는 점을 명심해야 합니다. 그렇지 않은 사용자 10% 의 경우, 사용자 환경이 망가지지는 않을 것입니다. 이 전략을 따르면 최악의 경우 사용자에게 기본 또는 '모바일'이 표시됩니다. 일부 구성요소의 레이아웃을 조정할 수 있습니다.

절충할 때는 모든 사용자에게 일관적이지만 수준은 낮은 환경을 제공하는 최소 공통분모 방식을 기본값으로 설정하기보다 대다수의 사용자를 위해 최적화하는 것이 좋습니다.

따라서 브라우저 지원 부족으로 인해 컨테이너 쿼리를 사용할 수 없다고 생각하기 전에, 컨테이너 쿼리를 채택하기로 한 경우 환경이 어떨지 생각해 보는 시간을 가지세요. 이러한 절충안은 대체가 없더라도 충분히 그만한 가치가 있을 수 있습니다.

향후 계획

이 게시물을 통해 현재 프로덕션에서 컨테이너 쿼리를 사용할 수 있으며, 지원되지 않는 모든 브라우저가 완전히 사라질 때까지 몇 년을 기다리지 않아도 된다는 확신을 주셨기를 바랍니다.

여기에 설명된 전략에는 약간의 추가 작업이 필요하지만 대부분의 사용자가 사이트에서 채택할 수 있을 만큼 간단하고 간단해야 합니다. 그렇긴 하지만, 확실히 더 쉽게 채택할 수 있는 여지는 있습니다. 한 가지 아이디어는 많은 이질적인 부분을 모든 글루 작업을 처리해 주는 단일 구성요소(특정 프레임워크 또는 스택에 최적화된)로 통합하는 것입니다. 이와 같은 콘텐츠를 제작하는 경우 저희에게 알려주시면 홍보에 도움을 드리겠습니다.

마지막으로, 컨테이너 쿼리 외에도 모든 주요 브라우저 엔진에서 상호 운용할 수 있는 놀라운 CSS 및 UI 기능이 많이 있습니다. 커뮤니티로서 이러한 기능을 실제로 어떻게 사용하여 사용자가 혜택을 얻을 수 있는지 알아봅시다.


업데이트 (2024년 7월 25일): 원래 '1단계' 안내 는 미디어 쿼리와 컨테이너 쿼리가 동일한 크기 조건을 사용할 수 있음을 시사했습니다. 이는 종종 사실이기는 하지만 항상 그런 것은 아닙니다(몇 가지 이유(예: 올바르게 지목된 이유)). 업데이트된 안내에서는 이제 이를 명확히 설명하고 크기 조건을 변경해야 할 수도 있는 사례 사례를 제공합니다.

업데이트 (2024년 7월 2일): 원래 모든 CSS 코드 예시에 Sass를 사용했습니다 (최종 권장사항과의 일관성을 위해). 독자의 의견에 따라 처음 몇 개의 CSS는 일반 CSS로 업데이트되었으며 Sass는 믹스인 사용이 필요한 코드 샘플에서만 사용됩니다.