Головна / Статті

Container Queries проти Media Queries: рішення щодо сторінки та компонентів

Дізнайтеся, коли варто використовувати медіа-запит, а коли краще підходить контейнерний запит, за допомогою прикладів у вигляді карток, панелей керування та одиниць, які дозволяють адаптувати повторно використовувані компоненти.

Видавець: REACTAPP.TOP16 хв читання3602 слів

Джерела: Container Queries vs Media Queries: How Modern CSS Changes Responsive Design

Більшість різковідповідних CSS-рішень все ще залежать від одного параметра – ширини вікна браузера. Це добре працює для всієї сторінки, але не підходить для повторно використовуваних компонентів, адже карточка, відображена у бічній панелі, та та сама карточка, відображена у широкому основному стовпці, бачать абсолютно однаковий простір відображення, хоча мають дуже різну кількість вільного простору. У цьому посібнику показано, як контейнерні запити закривають цю прогалину, де медіазапити залишаються кращим інструментом, та як поєднати обидва підходи з флуїдними одиницями для створення різковідповідної системи, яку можна логічно аналізувати.

Класичне правило, засноване на просторі відображення, виглядає так: як тільки ширина вікна опускається нижче певної межі, карточка викладає свій вміст вертикально.

@media (max-width: 768px) {
  .card {
    flex-direction: column;
  }
}

Нічого тут не зламано. Проблема полягає у концепції: правило вивчає, наскільки широке вікно, але ніколи — наскільки широка картка. У невеликій демонстрації ці значення супроводжують одне одного; у додатку, наповненому сітками, бічними панелями та іншими елементами, вони розходяться, і саме ця різниця стає причиною помилок у макетуванні. Запити контейнерів дозволяють компоненту запитати „Скільки саме простору у мене є?“ замість „Наскільки широкий екран?“.

Чому межа перегляду вводить в оману повторно використовувану картку

Візьмемо звичайну картку продукту: зображення поруч із блоком тексту з заголовком, коротким описом та закликом до дії. Маркування розділене тут на два фрагменти, але це один елемент.

<article class="product-card">
  <img src="product.jpg" alt="Product">
  <div class="product-info">
    <h2>Wireless Headphones</h2>
    <p>Noise cancellation with 30-hour battery life.</p>
    <button>Buy now</button>
  </div>
</article>

Під час першої обробки стилів зазвичай зображення та текст розміщуються поруч за допомогою flexbox, а потім додається межа перегляду для їхнього складання на малих екранах.

.product-card {
  display: flex;
  gap: 1rem;
}
@media (max-width: 768px) {
  .product-card {
    flex-direction: column;
  }
}

Це здається нормальним, поки картку не використовують знову. На широкій сторінці робочого столу є достатньо горизонтального простору, і розташування карток поруч виглядає правильно.

Desktop page
┌───────────────────────────────────────────┐
│                                           │
│   Product Card                            │
│   ┌──────────┐  ┌─────────────────────┐   │
│   │  Image   │  │ Product information │   │
│   └──────────┘  └─────────────────────┘   │
│                                           │
└───────────────────────────────────────────┘

Якщо помістити ту саму картку у вузький бічний панель, їй потрібне стекове розташування, навіть якщо вікно все ще залишається розміром з робочий стіл.

┌───────────────┐
│               │
│   Sidebar     │
│               │
│ ┌───────────┐ │
│ │   Image   │ │
│ ├───────────┤ │
│ │   Info    │ │
│ └───────────┘ │
│               │
└───────────────┘

Якщо розмістити кілька таких карток у одному ряду панелі керування, кожна картка отримує різну частку ширини залежно від своєго стовпця.

┌───────────────────────────────────────────┐
│ ┌─────────────┐ ┌──────────────────────┐ │
│ │   Card      │ │       Card           │ │
│ └─────────────┘ └──────────────────────┘ │
└───────────────────────────────────────────┘

Три варіанти розміщення, три різні ширини — один незмінний простір відображення. Правила, засновані на розмірах вікна, не можуть їх розрізнити, тому картка в бічному панелі залишається тісною.

У чому полягає справжня користь медіа-запитів

Запит медіа оцінює властивості середовища, у якому відображається сторінка: розміри вікна перегляду, орієнтація, схема кольорів, тип вказівника, налаштування щодо скороченого руху тощо. Знайомим прикладом є запит на ширину.

@media (max-width: 768px) {
  ...
}

Потік інформації простий: браузер вимірює вікно перегляду, запит підходить чи ні, і макет реагує на це.

Viewport
    ↓
Media Query
    ↓
Layout changes

Це робить запити медіа правильним інструментом для прийняття рішень, які справді стосуються всієї сторінки. Типовим прикладом є двоколонкова структура з фіксованою шириною бічної панелі:

.page-layout {
  display: grid;
  grid-template-columns: 1fr 300px;
}

При ширині вікна, меншій за певну величину, структура переходить у одноколонковий формат:

@media (max-width: 900px) {
  .page-layout {
    grid-template-columns: 1fr;
  }
}

Це правильне використання запиту медіа: наявність місця для бічної панелі дійсно є питанням вікна перегляду. Проблеми виникають, коли той самий механізм визначає, як окремий компонент організує свою внутрішню структуру.

Як працюють запити до контейнерів

Запит до контейнера дозволяє елементу реагувати на розмір предка, який ви显式 позначили як контейнер для запитів. Його налаштування вимагає двох кроків. Спочатку оголосіть контейнер:

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

Значення inline-size повідомляє браузеру, що нащадки можуть запитувати розмір контейнера у вигляді внутрішнього розміру, тобто його ширину у горизонтальному режимі виведення. Другий крок — написати правило для цього контейнера:

@container (max-width: 500px) {
  .product-card {
    flex-direction: column;
  }
}

Тепер інформація надходить від контейнера, а не від вікна:

Container
    ↓
Container Query
    ↓
Component layout

Карточка більше не залежить від того, чи використовує користувач телефон чи великий монітор; вона реагує на простір, який надає їй її батьківський елемент.

Один деталь, яка спричиняє плутанину

Запит до контейнера форматує нащадків контейнера, а не сам контейнер. Саме тому у прикладах завжди поєднується обгортка (.card-container, .card-wrapper) з внутрішнім елементом (.product-card). Якщо ви встановите container-type на .product-card, а потім зробите запит для зміни власного flex-direction цього елемента, нічого не станеться. Тримайте обгортку та компонент як окремі елементи.

Ще одна деталь: параметр inline-size означає, що ширину контейнера більше не можна визначити на основі його вмісту. Контейнер, який є блоковим дочірнім елементом у звичайному макеті, працює нормально, оскільки його ширина визначається батьківським елементом. Контейнер, який використовує механізм зменшення розміру до відповідності, наприклад елемент типу inline-block або елемент з абсолютним розташуванням без вказаної ширини, може зменшитися до нульової ширини після застосування цього параметра.

Ширина вікна перегляду проти ширини компонента

Цей контраст стає очевидним у панелі керування з широкою основною колонкою та вужчою бічною колонкою:

.dashboard {
  display: grid;
  grid-template-columns: 2fr 1fr;
  gap: 1rem;
}

Припустимо, що розмір вікна становить 1440 пкс. Правило, засноване на вікні перегляду для картки, буде виглядати так:

@media (max-width: 768px) {
  .card {
    flex-direction: column;
  }
}

У цьому вікні правило ніколи не застосовується. Проте картка, розташована у вужчій колонці, може мати ширину лише близько 350 пкс. Медіа-запит бере до уваги лише одне значення:

Viewport = 1440px

Карта знаходиться разом із іншою:

Component width = 350px

Лише друге число описує справжні умови карти, і лише запит контейнера може на це відреагувати.

Мінімальна налаштування запиту контейнера

Реалізація є короткою. Позначте обгортку як контейнер:

.card-wrapper {
  container-type: inline-size;
}

Надайте карті двоколонкову сітку, коли її контейнер має ширину принаймні 600 пкс:

@container (min-width: 600px) {
  .product-card {
    display: grid;
    grid-template-columns: 200px 1fr;
  }
}

У разі проблем використовуйте простий блочний макет:

@container (max-width: 599px) {
  .product-card {
    display: block;
  }
}

Для маркапу потрібен лише елемент-обгортка навколо карти:

<div class="card-wrapper">
  <article class="product-card">
    ...
  </article>
</div>

Тепер макет картки визначається її контейнером, тому переміщення обгортки в іншу колонку автоматично створює правильний макет. Зауважте, що два правила використовують min-width: 600px та max-width: 599px; за наявності дробових значень ширини контейнер може знаходитися між цими значеннями. Новіший синтаксис діапазону @container (width >= 600px) та @container (width < 600px) усуває цю прогалину, тому його варто використовувати у новому коді.

Чому це підходить для архітектури на основі компонентів

Запити до контейнерів мають більше значення, ніж звичайна нова функція CSS, оскільки сучасні фронтенди складаються з повторно використовуваних елементів – чи то компоненти фреймворків у React, Vue чи Angular, Web Components без фреймворку, чи то базові елементи спільної системи дизайну. Жоден з цих елементів не повинен знати, у якій області сторінки він опиниться. Розглянемо елемент user-card. Він може відображатися у основній області контенту:

<main>
  <user-card></user-card>
</main>

Він також може відображатися у боковій панелі:

<aside>
  <user-card></user-card>
</aside>

Або його може бути кілька екземплярів у сітці панелі керування:

<div class="dashboard-grid">
  <user-card></user-card>
  <user-card></user-card>
  <user-card></user-card>
</div>

Жорстке вкодування значення порогу перегляду у цей компонент передбачає наявність припущення, яке неможливо перевірити:

@media (max-width: 768px) {
  ...
}

Число 768 нічого не говорить про справжній контекст компонента. Запит контейнера пропонує кращі умови: при наявності певного простору використовувати саме цей макет. Якщо ваші компоненти є незалежними від фреймворку елементами, обговорення того, де має знаходитися межа фреймворку в багаторазовій стеку інтерфейсу є корисним доповненням до цієї ідеї.

Дозволити картці профілю адаптуватися до оточення

Ось компактна картка профілю, яка розміщує аватар поруч із іменем та посадою:

.profile-card {
  display: flex;
  gap: 1rem;
  align-items: center;
}

Її обгортка стає контейнером запиту:

.profile-container {
  container-type: inline-size;
}

Коли ширина цього контейнера становить 400 пкс або менше, картка складає свій вміст та центрує його:

@container (max-width: 400px) {
  .profile-card {
    flex-direction: column;
    text-align: center;
  }
}

У просторому контейнері аватар розташовується поруч із текстом:

┌──────────────────────────────────────┐
│ [Avatar]  John Smith                 │
│           Senior Developer           │
└──────────────────────────────────────┘

У критичній ситуації той самий компонент переставляє себе вертикально:

┌──────────────────┐
│                  │
│     [Avatar]     │
│                  │
│    John Smith    │
│ Senior Developer │
│                  │
└──────────────────┘

Немає спостерігача за зміною розміру, немає другої „компактної“ версії, немає класу, який би активувався сторінкою-батьком.

У медіа-запитах все ще є роль

Запити контейнера не замінюють медіа-запити; вони відповідають на інше питання. Ось швидкий спосіб класифікувати поширені рішення:

  • Згортання основного меню: медіа-запит.
  • Видалення бічної панелі на рівні сторінки: медіа-запит.
  • Зміна розташування картки з горизонтального на вертикальний: запит контейнера.
  • Адаптація повторно використовуваного компонента під своє місце розташування: запит контейнера.
  • Коригування типографіки на всьому сайті: медіа-запит.
  • Дозволити віджету панелі керування реагувати на ширину своєї колонки: запит контейнера.
  • Зміна розташування всього корпусу додатку на інше: медіа-запит.
  • Зміна поведінки компонента всередині вузького батьківського елемента: запити контейнера.
  • Ментальна модель: глобальні рішення та рішення компонентів

    Найзрозуміліший спосіб розділення завдань — це відокремити те, що вирішує сторінка, від того, що вирішує кожен компонент.

    Запити медіа стосуються вікна перегляду

    Питання, яке стоїть за запитом медіа, полягає у:

    "What is the viewport doing?"
    

    Вони підходять для:

    • Структури сторінки
    • Навігації
    • Глобального відступу
    • Глобальної типографіки
    • Значних змін лейауту

    Запити контейнера стосуються оточення компонента

    Питання, яке стоїть за запитом контейнера, полягає у:

    "What is my component's environment doing?"
    

    Вони підходять для:

    • Карток
    • Віджетів
    • Панелей
    • Багаторазово використовуваних компонентів інтерфейсу
    • Модулів панелі керування
    • Компонентів системи дизайну

    Розміркування за допомогою одиниць запитів контейнера

    Запити контейнерів — це не лише умовні блоки. CSS також визначає одиниці довжини відносно найближчого контейнера-запиту, тож значення можуть поступово змінюватися, а не різко змінюватися при досягненні певної межі:

    .title {
      font-size: 5cqi;
    }
    

    Тут cqi означає один відсоток внутрішнього розміру контейнера, тож 5cqi — це п’ять відсотків його ширини. Повний набір одиниць:

    cqw  → container width
    cqh  → container height
    cqi  → container inline size
    cqb  → container block size
    cqmin → smaller container dimension
    cqmax → larger container dimension
    

    Поширеним підходом є обгортання одиниці контейнера у функцію clamp(), щоб значення змінювалося разом із контейнером, але завжди залишалося в розумних межах:

    .card-title {
      font-size: clamp(1rem, 4cqi, 2rem);
    }
    

    Тепер заголовок масштабується відповідно до простору компонента, а не вікна, що робить неможливим використання таких одиниць перегляду, як vw. Є два застереження. Якщо елемент не має батьківського контейнера для обчислень, ці одиниці переходять на менші одиниці перегляду, тож значення все одно буде отримано, але не те, яке ви очікували. Крім того, використання значень мінімуму та максимуму для rem всередині функції clamp(), як описано вище, має значення для доступності: розмір шрифту, який визначається виключно шириною контейнера, не реагує на налаштування розміру тексту користувача.

    Найменування контейнерів у більших додатках

    Для невеликої сторінки достатньо анонімного контейнера:

    .container {
      container-type: inline-size;
    }
    

    Коли контейнери вкладені один у одного, просте правило @container відповідає найближчому батьківському контейнеру, який може не бути тим, що ви мали на увазі. Скорочення container дозволяє надати контейнеру ім’я разом із його типом:

    .dashboard {
      container: dashboard / inline-size;
    }
    

    Потім правила можуть безпосередньо адресувати саме цей контейнер:

    @container dashboard (min-width: 700px) {
      .widget {
        grid-template-columns: 1fr 1fr;
      }
    }
    

    Порівняйте умову без імені:

    @container (min-width: 700px)
    

    з умовою з іменем:

    @container dashboard (min-width: 700px)
    

    Версія з іменем чітко визначає свою мету та продовжує працювати навіть у разі, якщо хтось пізніше додасть ще один контейнер між панеллю керування та віджетом.

    Ретельно обирайте межі контейнерів

    Запити до контейнерів є потужними, але це не причина додавати таку декларацію до кожного елемента:

    container-type: inline-size;
    

    Кожен контейнер застосовує макетування, стиль та параметри розміру елемента, що змінює спосіб його форматування, тому контейнери повинні визначати чіткі межі компонентів, а не розташовуватися всюди. Розгляньмо панель керування з віджетами всередині неї:

    <section class="dashboard">
      <article class="widget">
        <div class="widget-content">
          ...
        </div>
      </article>
    </section>
    

    Розумним вибором є зробити саму панель керування іменованим контейнером:

    .dashboard {
      container: dashboard / inline-size;
    }
    

    і дозволити кожному віджету реагувати на неї. Правило полягає не у «використанні контейнерних запитів скрізь», а у «їх використанні там, де поведінка залежить від доступного простору».

    Заміна точок переривання на основі розміру екрана на точки переривання, засновані на контенті

    Багато таблиць стилів містять ієрархію точок переривання для вікна перегляду у такому форматі:

    @media (max-width: 1200px) {
      ...
    }
    
    @media (max-width: 1024px) {
      ...
    }@media (max-width: 900px) {
      ...
    }@media (max-width: 768px) {
      ...
    }@media (max-width: 640px) {
      ...
    }@media (max-width: 480px) {
      ...
    }
    

    Іноді така структура є обґрунтованою. Часто вона свідчить про те, що компоненти були розроблені з урахуванням ширини пристрою, а не їхнього власного контенту. Запити до контейнерів спонукають нас задаватися іншими питаннями. Замість того, щоб запитувати «Який рівень переривання зазвичай використовує команда?», потрібно запитати «При якій ширині цей компонент перестає виглядати правильно?» Відповідь дає нам рівень переривання, заснований на контенті:

    @container (max-width: 420px) {
      .card {
        flex-direction: column;
      }
    }
    

    Цифра 420px не відповідає конкретному телефону; це ширина, при якій у картці закінчується місце. Рівні переривання, обрані таким чином, залишаються актуальними після змін макету та появи нових пристроїв.

    Розробка компонентів, які не залежать від розташування

    Запити до контейнерів також спонукають команди створювати справді незалежні компоненти, поведінка яких є передбачуваною незалежно від місця їхнього відображення. Уявіть собі групу кнопок у системі дизайну. Вона може знаходитися всередині форми на сторінці:

    Page
     └── Form
          └── Button Group
    

    всередині картки на панелі керування:

    Dashboard
     └── Card
          └── Button Group
    

    або всередині картки в бічній панелі:

    Sidebar
     └── Card
          └── Button Group
    

    Вікно перегляду є ідентичним у всіх трьох випадках; простір — ні. За допомогою запиту контейнера група адаптується, не знаючи нічого про структуру над нею.

    Багаторазовий респонсивний шаблон картки

    Ось повний шаблон, який ви можете використовувати без змін. Маркап обгортає картку елементом-контейнером; знову ж таки, HTML показаний у двох послідовних частинах.

    <div class="card-container">
      <article class="card">
        <img src="image.jpg" alt="">
    
        <div class="card-content">
          <h2>Performance Dashboard</h2>
          <p>
            Monitor application performance and infrastructure metrics.
          </p>
          <a href="#">View dashboard</a>
        </div>
      </article>
    </div>
    

    Обгортка оголошується як контейнер:

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

    Карта спочатку має формат одноколонкової сітки з зображенням у співвідношенні 16:9. Коли її контейнер досягає розміру 600px, вона переходить на формат із фіксованою колонкою зображення поруч із контентом та робить зображення квадратним. Правила описані без перерв між рядками, що є допустимим у CSS, але варто їх переформатувати під час вставки до кодової бази.

    .card {
      display: grid;
      gap: 1rem;
    }.card img {
      width: 100%;
      aspect-ratio: 16 / 9;
      object-fit: cover;
    }@container (min-width: 600px) {
      .card {
        grid-template-columns: 200px 1fr;
        align-items: center;
      }  .card img {
        aspect-ratio: 1;
      }
    }
    

    Зверніть увагу, чого не містить цей стильовий файл:

    @media (max-width: 768px)
    

    Карта ніколи не враховує розмір вікна перегляду. Усі її рішення ґрунтуються лише на її контейнері.

    Поєднання запитів до контейнера з автоматичною сіткою

    Запити до контейнера особливо добре поєднуються із сіткою, яка сама визначає кількість своїх колонок:

    .dashboard {
      display: grid;
      grid-template-columns:
        repeat(auto-fit, minmax(280px, 1fr));
      gap: 1rem;
    }
    

    За допомогою repeat(auto-fit, minmax(280px, 1fr)) браузер розміщує стільки колон шириною щонайменше 280px, скільки дозволяє рядок, та розтягує їх, щоб заповнити залишковий простір. Кожен віджет отримує свій власний контейнер:

    .widget-container {
      container-type: inline-size;
    }
    

    і переходить на внутрішню двоколонну структуру, коли його поле достатньо широке:

    @container (min-width: 500px) {
      .widget {
        grid-template-columns: 1fr 1fr;
      }
    }
    

    Панель керування адаптується до різних ширин без використання точок переривання вікна перегляду: сітка визначає, скільки простору отримає кожен віджет, а кожен віджет вирішує, як ним скористатися.

    Респонсивний дизайн також стосується зручності використання

    Те, що елементи вміщуються на екрані, не означає, що вони легко використовуватися. Рядок кнопок, який технічно поміщається на вузькій картці, все одно може бути занадто тісним та ускладнювати натискання. Завдяки контейнерним запитам дії можна скласти в один ряд та розтягнути їх на повну ширину, коли картка вузька (правило реалізоване у двох фрагментах коду):

    @container (max-width: 350px) {
      .actions {
        flex-direction: column;
      }
    
      .actions button {
        width: 100%;
      }
    }
    

    Кнопки, розташовані у один ряд по всю ширину, створюють більші зони для натискання та зменшують кількість випадкових дотиків. Те саме принцип можна застосувати до тексту – його розмір має змінюватися в межах можливого, коли змінюється ширина компонента:

    .card-title {
      font-size: clamp(1rem, 4cqi, 1.75rem);
    }
    

    Конкретні значення мають менше значення, ніж принцип, який за ними стоїть: реактивна поведінка має відображати умови, за яких фактично використовується компонент, а не припущення, засновані на розмірі вікна.

    Коли медіа-запити залишаються правильним вибором

    Контейнерні запити не є автоматично кращим варіантом. Глобальна навігація є яскравим прикладом для використання медіа-запиту, адже приховування повного меню та відображення кнопки меню є рішенням, пов’язаним із структурою сторінки (це правило також поділяється на два пункти):

    @media (max-width: 900px) {
      .navigation {
        display: none;
      }
    
      .menu-button {
        display: block;
      }
    }
    

    Персоналізовані налаштування користувача — це зовсім інша категорія. Зменшення швидкості анімацій для користувачів, які попросили свою операційну систему менше анімацій, не має нічого спільного з контейнерами:

    @media (prefers-reduced-motion: reduce) {
      * {
        animation-duration: 0.01ms;
        animation-iteration-count: 1;
      }
    }
    

    Це налаштування середовища, які можуть читатися лише за допомогою запитів до медіа. Метою не є усунення запитів до медіа, а лише припинення їх використання для прийняття рішень щодо компонентів.

    Трирівневий підхід до респонсивного CSS

    Для застосунку, заснованого на компонентах, корисно розглядати респонсивне форматування у трьох рівнях.

    Рівень 1: глобальна респонсивність за допомогою запитів до медіа

    Запити до медіа вирішують проблеми, які стосуються всієї сторінки:

    Page layout
    Navigation
    Global typography
    Major structural changes
    Application shell
    

    Рівень 2: респонсивність компонентів за допомогою запитів до контейнерів

    Запити до контейнерів вирішують питання внутрішнього макету самостійних елементів:

    Cards
    Widgets
    Panels
    Reusable components
    Design-system components
    Dashboard modules
    

    Рівень 3: плавна поведінка за допомогою функцій та одиниць вимірювання

    Там, де не потрібні жорсткі точки переривання, дозвольте значенням поступово змінюватися за допомогою сучасних функцій та одиниць вимірювання:

    clamp()
    min()
    max()
    minmax()
    cqi
    cqw
    

    Наприклад, заголовок може зростати разом із своїм контейнером у межах двох фіксованих значень:

    .heading {
      font-size: clamp(1.5rem, 3cqi, 3rem);
    }
    

    Разом ці рівні утворюють систему, а не набір окремих рішень щодо точок переривання.

    Справжня зміна — це те, хто приймає рішення

    Є спокуса описувати запити до контейнерів як „запити до медіа для елементів“. Це технічно точно, але не відображає суті. Змінюється модель відповідальностей. У традиційному респонсивному CSS сторінка фактично визначає, як буде поводитися кожен компонент:

    Viewport
       ↓
    Media Query
       ↓
    Component
    

    За допомогою запитів до контейнерів кожен компонент отримує вказівки від свого власного контейнера:

    Component Container
            ↓
    Container Query
            ↓
    Component
    

    Компоненти, які мають власні правила адаптивності, легше повторно використовувати, переміщувати, тестувати окремо та підтримувати. Саме ця зміна в формі власності є довгостроковою перевагою.

    Одне запитання для вирішення кожного випадку

    Коли ви не впевнені, який інструмент використати, запитайте себе, чи стосується рішення щодо макету сторінки чи компонента. Якщо це стосується сторінки, використовуйте запити медіа. Якщо це стосується простору, який виділено для компонента, використовуйте запити контейнера. Це стосується типових випадків:

    Should the sidebar disappear?
            ↓
        Media Query
    
    Should this card switch from horizontal
    to vertical?
            ↓
      Container Query
    
    Should the navigation collapse?
            ↓
        Media Query
    
    Should this reusable widget change
    its internal layout?
            ↓
      Container Query
    

    Основні висновки

    • Запити медіа описують вікно перегляду та середовище користувача, тому вони підходять для структури сторінки, навігації, глобальної типографіки та налаштувань, таких як скорочена анімація.
    • Запити контейнера описують простір, який отримує компонент, тому вони підходять для карток, віджетів, панелей та компонентів дизайн-системи.
  • Запити контейнерів форматують нащадків контейнера; тримайте контейнер та компонент як окремі елементи та стежте за контейнерами, яким потрібна ширина, залежна від контенту.
  • Роздільники, засновані на контенті, визначають момент, коли компонент більше не функціонує, і є більш стабільними, ніж ті, що залежать від пристрою.
  • Єдиниці контейнерів, такі як cqi та cqw, обгорнуті функцією clamp() з межами у rem, забезпечують гнучке форматування, не порушуючи налаштувань розміру тексту користувача.
  • Називайте контейнери після того, як вони будуть вкладені, та створюйте їх лише на значущих межах компонентів.
  • Найнадійніше рішення — поєднувати запити до медіа, запити контейнерів та гнучкий CSS, замість вибору лише одного з них.