Fluid-верстка на clamp() и CSS Container Queries: как раз и навсегда забыть про сотни @media брейкпоинтов в компонентах Битрикса
Rus
Eng
Fluid-верстка на clamp() и CSS Container Queries: как раз и навсегда забыть про сотни @media брейкпоинтов в компонентах Битрикса
Решаю сложные технические задачи для Bitrix и 1С: от аудита чужого кода до разработки сайтов и настройки сложных интеграций с гарантией результата
Рекомендую

Хостинг для сайта

Если выбираете хостинг под проект — советую Timeweb. Современная инфраструктура, широкий выбор тарифов от стартовых до VPS под нагрузку, отзывчивая техподдержка, которая отвечает по существу, а не отписками. Я сам держу на нём часть своих проектов и рекомендую клиентам.

Перейти Партнёрская ссылка. Для вас цена не меняется.

Почему классический адаптив в Битриксе превращается в кашу

Откройте любой коммерческий шаблон Bitrix, которому больше двух лет. В папке style.css каждого компонента — десятки, а то и сотни строк вида @media (max-width: 768px), @media (max-width: 480px), @media (min-width: 1200px). Карточка товара прописана отдельно для каталога, отдельно для слайдера «Вы смотрели», отдельно для мобильной версии. Перенесли карточку из широкой сетки в узкий сайдбар — верстка поехала, потому что она знает только про ширину экрана, но ничего не знает про ширину родителя.

Это не проблема конкретного проекта. Это системная проблема подхода, при котором компонент проектируется с оглядкой на вьюпорт, а не на контекст, в котором он реально живёт. И пока мы продолжаем писать медиа-запросы под каждый чих, будем перекладывать одни и те же костыли из компонента в компонент.

Часть 1. clamp() — жидкие значения без единого брейкпоинта

Функция clamp() принимает три значения: минимум, предпочтительное значение и максимум. Между минимумом и максимумом значение плавно интерполируется в зависимости от ширины вьюпорта. Никаких скачков, никаких «на 767px одно, на 768px другое».

font-size: clamp(1rem, 2.5vw, 2rem);

Здесь 1rem — это минимальный размер шрифта. 2rem — максимальный. 2.5vw — предпочтительное значение, которое масштабируется вместе с вьюпортом. Функция вернёт max(1rem, min(2.5vw, 2rem)), то есть не даст тексту стать меньше 1rem или больше 2rem, но между этими границами он будет масштабироваться плавно.

Как считать формулы руками

Вручную считать clamp() для каждого размера — муторно. Формула такая: наклон slope = (maxSize - minSize) / (maxVw - minVw), коэффициент vw — это slope * 100, свободный член — minSize - slope * minVw. Итоговое выражение выглядит как clamp(minSize, intercept + (slope * 100)vw, maxSize).

Пример: шрифт должен быть 16px на ширине 320px и 24px на 1200px. Наклон: (24 - 16) / (1200 - 320) = 0.00909. Коэффициент vw: 0.00909 * 100 = 0.909. Свободный член: 16 - 0.00909 * 320 = 13.09px ≈ 0.818rem. Результат: clamp(1rem, 0.818rem + 0.909vw, 1.5rem).

Ручной расчёт хорош для понимания, но в работе лучше использовать готовые инструменты или SASS/LESS-миксины, которые генерируют эти формулы прямо в сборке.

Жидкая типографика в шаблоне сайта

Начнём с общего шаблона. В Bitrix шаблон сайта — это header.php, footer.php и template_styles.css. Определим жидкие размеры шрифтов и отступов через CSS-переменные, чтобы они были доступны во всех компонентах.

:root {
    --font-size-xs: clamp(0.75rem, 0.7rem + 0.25vw, 0.875rem);
    --font-size-sm: clamp(0.875rem, 0.8rem + 0.35vw, 1rem);
    --font-size-base: clamp(1rem, 0.95rem + 0.25vw, 1.125rem);
    --font-size-lg: clamp(1.25rem, 1.1rem + 0.75vw, 1.75rem);
    --font-size-xl: clamp(1.75rem, 1.4rem + 1.5vw, 2.75rem);
    --font-size-2xl: clamp(2.25rem, 1.5rem + 3vw, 4rem);

    --space-xs: clamp(0.25rem, 0.2rem + 0.25vw, 0.5rem);
    --space-sm: clamp(0.5rem, 0.4rem + 0.5vw, 1rem);
    --space-md: clamp(1rem, 0.8rem + 1vw, 1.5rem);
    --space-lg: clamp(1.5rem, 1rem + 2vw, 3rem);
    --space-xl: clamp(2rem, 1.5rem + 3vw, 5rem);
}

Дальше в template_styles.css применяем эти переменные к базовым элементам.

body {
    font-size: var(--font-size-base);
    line-height: 1.6;
}

h1 { font-size: var(--font-size-2xl); }
h2 { font-size: var(--font-size-xl); }
h3 { font-size: var(--font-size-lg); }

.container {
    max-width: 1280px;
    margin-inline: auto;
    padding-inline: var(--space-md);
}

Никаких медиа-запросов для типографики. Заголовки, тексты и отступы масштабируются плавно от 320px до 1920px. Медиа-запросы остаются только для смены структуры: показать/скрыть сайдбар, переключить меню на бургер.

Каркас страницы: футер внизу, сайдбар сбоку, контент первым

.page {
    display: grid;
    grid-template-rows: auto 1fr auto;
    min-height: 100vh;
}

.page--has-sidebar {
    grid-template-columns: 1fr 320px;
    grid-template-areas:
        "header header"
        "content sidebar"
        "footer footer";
}

.page--has-sidebar-left {
    grid-template-columns: 320px 1fr;
    grid-template-areas:
        "header header"
        "sidebar content"
        "footer footer";
}

.page--header { grid-area: header; }
.page--content { grid-area: content; }
.page--sidebar { grid-area: sidebar; }
.page--footer { grid-area: footer; }

Ключевой момент: в разметке контентная область должна идти перед сайдбаром, чтобы при линейном чтении основной контент был доступен первым. grid-template-areas позволяет расположить его визуально справа или слева независимо от порядка в HTML.

@media (max-width: 1024px) {
    .page--has-sidebar,
    .page--has-sidebar-left {
        grid-template-columns: 1fr;
        grid-template-areas:
            "header"
            "content"
            "sidebar"
            "footer";
    }
}

Медиа-запрос управляет структурой, а не размерами. Размеры внутри колонок — жидкие, через clamp().

Отступы между блоками

.section {
    padding-block: var(--space-xl);
}

.section--compact {
    padding-block: var(--space-lg);
}

.grid--cards {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 280px), 1fr));
    gap: var(--space-md);
}

minmax(min(100%, 280px), 1fr) — важная деталь. Без min(100%, 280px) на очень узких экранах колонка может оказаться шире контейнера и вызвать горизонтальный скролл.

Часть 2. Container Queries — компонент сам знает, где он живёт

Медиа-запросы реагируют на вьюпорт. Контейнерные запросы реагируют на ширину родительского блока. Разница принципиальная: одна и та же карточка товара может лежать в широкой сетке каталога, в узком слайдере «Вы смотрели» и в модальном окне. С медиа-запросами придётся писать три набора стилей. С контейнерными — один.

container-type: inline-size против size

Контейнерный запрос работает только если у элемента явно задан container-type. Два значения, которые нужны на практике.

inline-size — контейнер замеряет свою ширину, размеры по блочной оси продолжают зависеть от содержимого. Это значение нужно в 95% случаев: карточки, фильтры, слайдеры — всё, что реагирует на ширину родителя.

size — контейнер замеряет и ширину, и высоту. Нужен, когда в запросе используются cqh или cqb, либо когда компонент должен сам управлять своей высотой внутри родителя. Опасность в том, что size устанавливает contain: size: родитель перестаёт видеть содержимое контейнера, и если высота не задана явно — блок схлопнется в ноль. Ставить size без острой необходимости не стоит.

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

Важно понимать, что container-type устанавливает contain: layout style inline-size (или size для второго варианта). Это значит, что позиционированные потомки начинают считаться от контейнера, а не от более дальнего предка, и выносные элементы (например, position: fixed внутри) могут вести себя иначе. Если внутри карточки есть тултип с абсолютным позиционированием, он будет позиционироваться относительно карточки, а не страницы.

Главная методологическая ошибка: контейнер не на сетке

Самый частый неверный пример, который гуляет по статьям, выглядит так:

/* Так делать не надо */
.catalog--grid {
    container-type: inline-size;
    container-name: catalog-grid;
}

@container catalog-grid (min-width: 400px) {
    .product-card {
        flex-direction: row;
    }
}

Проблема в том, что контейнерный запрос смотрит на ширину всей сетки, а не на ширину ячейки, в которой лежит конкретная карточка. Если сетка 1200px и в ней три колонки по 380px, запрос всё равно сработает (сетка-то больше 400px), и все карточки станут горизонтальными, хотя каждая из них живёт в узкой ячейке. Ещё хуже: на мобильном сетка 360px, а ячейка 360px — вроде всё совпадает. Но стоит добавить сайдбар или перенести сетку в узкую область — запрос снова начнёт врать.

Правильный паттерн: контейнер ставится на обёртку каждого элемента, а не на общую сетку. Каждая карточка реагирует на ширину своей ячейки.

.catalog--grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 280px), 1fr));
    gap: var(--space-md);
}

.catalog--item {
    container-type: inline-size;
    container-name: product-card;
}

.product-card {
    display: flex;
    flex-direction: column;
    gap: var(--space-sm);
    padding: var(--space-sm);
    border: 1px solid var(--color-border);
    border-radius: 8px;
}

@container product-card (min-width: 400px) {
    .product-card {
        flex-direction: row;
        align-items: center;
    }
}

В HTML каждая карточка обёрнута в .catalog--item. Именно эта обёртка — контейнер, а карточка внутри — уже её содержимое, которое можно стилизовать по запросу. Контейнер не может стилизовать сам себя, только своих потомков, поэтому обёртка обязательна.

container-name и вложенные контейнеры

Имя контейнера не обязательно, но полезно, когда контейнеры вложены друг в друга. Без имени запрос ищет ближайший контейнер с подходящим container-type, и если карточка лежит внутри слайдера, который сам является контейнером, вы получите не тот результат, который ожидали.

.slider--track {
    container-type: inline-size;
    container-name: product-slider;
}

.slider--item {
    container-type: inline-size;
    container-name: product-card;
}

/* Явно адресуемся к контейнеру карточки, а не слайдера */
@container product-card (min-width: 400px) {
    .product-card {
        flex-direction: row;
    }
}

/* Явно адресуемся к контейнеру слайдера */
@container product-slider (max-width: 500px) {
    .slider--item {
        flex-basis: 200px;
    }
}

Если имён нет, и запросы вложены, порядок объявлений становится критичен: спецификация гласит, что при совпадении нескольких контейнеров выбирается ближайший подходящий. На практике это значит, что внутри слайдера @container (min-width: 400px) будет смотреть на ячейку слайдера, а не на трек. Явные имена снимают эту неопределённость.

Единицы cqw, cqh, cqi, cqb

Внутри контейнера доступны свои единицы измерения:

  • cqw — 1% от ширины контейнера;
  • cqh — 1% от высоты контейнера (требует container-type: size);
  • cqi — 1% от inline-размера контейнера (в горизонтальной раскладке равен cqw);
  • cqb — 1% от block-размера контейнера (в горизонтальной раскладке равен cqh).

Это ключевая деталь, которой нет в примерах на vw: жидкие размеры внутри компонента можно делать относительно его контейнера, а не вьюпорта.

@container product-card (min-width: 300px) {
    .product-card--title {
        font-size: clamp(0.875rem, 6cqi, 1.25rem);
        padding-block: clamp(0.5rem, 3cqi, 1rem);
    }

    .product-card--image {
        flex-basis: clamp(100px, 35cqi, 180px);
    }
}

В широкой ячейке шрифт вырастет до 1.25rem, в узкой упадёт до 0.875rem. Никаких вьюпортов в расчёте — только ширина родителя, в котором реально живёт карточка. Если карточку перенести из каталога в сайдбар, шрифт пересчитается автоматически.

Карточка товара в catalog.section

Собираем всё вместе. Разметка — с обёрткой на каждом элементе, стили — через контейнерные запросы, данные экранируются.

<div class="catalog--grid">
    <?php foreach ($arResult['ITEMS'] as $arItem): ?>
        <div class="catalog--item">
            <div class="product-card">
                <div class="product-card--image">
                    <img src="<?=htmlspecialcharsbx($arItem['PREVIEW_PICTURE']['SRC'])?>"
                         alt="<?=htmlspecialcharsbx($arItem['NAME'])?>">
                </div>
                <div class="product-card--body">
                    <div class="product-card--title"><?=htmlspecialcharsbx($arItem['NAME'])?></div>
                    <div class="product-card--price"><?=htmlspecialcharsbx($arItem['PRICE'])?> ₽</div>
                    <button class="product-card--buy" type="button">В корзину</button>
                </div>
            </div>
        </div>
    <?php endforeach; ?>
</div>

Карточка не знает, где она находится. Она знает только ширину родительской обёртки .catalog--item. Если обёртка узкая — вертикальная раскладка, если широкая — горизонтальная. Перенесли карточку в слайдер — она автоматически перестроилась.

Внимание: ссылка на пример

Слайдер товаров

Слайдер — классический пример, где контейнерные запросы экономят часы работы. Раньше приходилось держать отдельный шаблон для слайдера с урезанной версткой карточки. Теперь можно использовать один шаблон и один набор стилей.

Контейнер ставим на каждую ячейку слайдера, а не на трек. Трек — это общая лента, её ширина всегда больше ширины отдельной ячейки, и запрос на треке опять начнёт врать.

.slider--track {
    display: flex;
    gap: var(--space-sm);
    overflow-x: auto;
    scroll-snap-type: x mandatory;
}

.slider--item {
    flex: 0 0 clamp(200px, 60vw, 280px);
    scroll-snap-align: start;
    container-type: inline-size;
    container-name: product-card;
}

В слайдере карточка всегда вертикальная, потому что обёртка .slider--item узкая. В сетке каталога — горизонтальная, потому что обёртка широкая. Один компонент, разные контексты.

Внимание: ссылка на пример

Фильтр в каталоге

Фильтр — ещё один компонент, который страдает от контекста. В сайдбаре он вертикальный, в мобильной версии — выезжающая панель, в горизонтальной раскладке — строка чекбоксов.

.filter--wrapper {
    container-type: inline-size;
    container-name: filter-panel;
}

.filter--group {
    display: flex;
    flex-direction: column;
    gap: var(--space-xs);
}

@container filter-panel (min-width: 600px) {
    .filter--group {
        flex-direction: row;
        flex-wrap: wrap;
        align-items: center;
        gap: var(--space-sm);
    }

    .filter--label {
        white-space: nowrap;
    }
}

@container filter-panel (max-width: 400px) {
    .filter--group {
        padding: var(--space-xs);
    }

    .filter--label {
        font-size: var(--font-size-xs);
    }
}

Обратите внимание: container-type задан на .filter--wrapper, а не на самой группе. Контейнерный запрос не может применяться к элементу, который сам является контейнером — нужен родитель.

Внимание: ссылка на пример

@supports и fallback для старых браузеров

Container Queries поддерживаются во всех актуальных браузерах с 2023 года: Chrome 105+, Firefox 110+, Safari 16+. Для проектов, которые должны работать и в чём-то более старом, нужна стратегия fallback.

Правильный подход — progressive enhancement: базовые стили пишутся для медиа-запросов, а поверх через @supports добавляются контейнерные.

/* Базовый вариант для всех браузеров */
.product-card {
    display: flex;
    flex-direction: column;
}

@media (min-width: 768px) {
    .product-card {
        flex-direction: row;
        align-items: center;
    }
}

/* Переопределяем для браузеров с Container Queries */
@supports (container-type: inline-size) {
    .catalog--item,
    .slider--item {
        container-type: inline-size;
        container-name: product-card;
    }

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

    @container product-card (min-width: 400px) {
        .product-card {
            flex-direction: row;
            align-items: center;
        }
    }
}

Старые браузеры увидят только медиа-запросы и получат фиксированную раскладку. Современные — перейдут на контейнерные запросы, потому что блок @supports перебьёт базовое правило.

clamp() поддерживается ещё шире: Chrome 79+, Firefox 75+, Safari 13.1+. Здесь проблем с поддержкой нет.

Style queries и scroll-state queries

Кроме размерных запросов, в спецификацию вошли ещё два типа. Style queries (@container style(--theme: dark)) позволяют реагировать на значение CSS-переменной или пользовательского свойства, а не на размер. Это открывает путь к переключению темы внутри компонента без JS.

@container style(--density: compact) {
    .product-card {
        padding-block: var(--space-xs);
        gap: var(--space-xs);
    }
}

Scroll-state queries (@container scroll-state(stuck: top)) позволяют реагировать на состояние скролла: прилип ли элемент к краю, виден ли он в вьюпорте контейнера, докручен ли до конца. Для sticky-хедеров и lazy-загрузки это то, что раньше делалось через IntersectionObserver.

Обе технологии на 2026 год поддерживаются частично: style queries уже есть в стабильных Chrome и Safari, scroll-state queries — в Chrome 133+ и в свежих Safari. Использовать их стоит через @supports и не полагаться на них как на единственное решение.

Производительность и containment

Каждый контейнер устанавливает containment — браузер изолирует внутренние стили и layout от внешнего мира. Это само по себе ускоряет перерасчёт: изменение внутри контейнера не вызывает reflow наружу. Но контейнеров не должно быть слишком много.

Правила простые. Один контейнер на переиспользуемый компонент, а не на каждый элемент. Не ставить container-type на элементы с position: fixed внутри. Не ставить container-type: size на элементы, у которых высота зависит от содержимого: они схлопнутся. Если на странице пятьсот карточек в длинном списке — контейнер на обёртке каждой карточки нормален, но не надо добавлять туда же ещё контейнеры на заголовок, цену и кнопку отдельно.

Часть 3. Интеграция в Битрикс-проект

Где держать глобальные переменные

Все clamp()-переменные и базовые токены лучше объявлять в template_styles.css шаблона сайта. Этот файл подключается на всех страницах, и переменные доступны любому компоненту. Если компонент переиспользуется в нескольких проектах, локальные переменные можно продублировать в style.css самого компонента.

/* template_styles.css */
:root {
    --font-size-base: clamp(1rem, 0.95rem + 0.25vw, 1.125rem);
    --space-md: clamp(1rem, 0.8rem + 1vw, 1.5rem);
    --color-border: #e0e0e0;
}

Проблема с обёртками в шаблонах Bitrix

Ключевое отличие от верстки на чистом HTML: в компонентах Bitrix нельзя просто взять и обернуть каждый элемент в div. Шаблон отрисовывается циклом, и добавлять промежуточные обёртки в разметку — значит править шаблон. Хорошая новость: править шаблон в /local — штатный механизм Bitrix, и делать это нужно.

Если шаблон компонента лежит в /bitrix/components/bitrix/catalog.section/templates/.default/ и менять его не хочется, его копируют в /local/templates/<шаблон_сайта>/components/bitrix/catalog.section/<имя_шаблона>/. Дальше правят только копию. Обновления Bitrix её не тронут.

Три штатных места, куда можно добавить код без правки самого template.php:

  • result_modifier.php — обработка $arResult перед выводом. Сюда можно добавить классы и обёртки в массив, но не в разметку.
  • component_epilog.php — выполняется после шаблона. Сюда удобно подключать дополнительные ассеты через Asset::addCss() и Asset::addJs(), но не менять разметку.
  • style.css в папке шаблона компонента — подключается автоматически. Здесь живут все стили компонента.

Обёртку в разметку добавляет только сам template.php. Это одна строка, и её появление в шаблоне — не «лишний div», а техническая необходимость для контейнерных запросов.

Как быть с catalog.section, sale.basket, news.list

Для каждого стандартного компонента Bitrix паттерн одинаковый: скопировать шаблон в /local, добавить обёртку вокруг каждого элемента, повесить на неё container-type в style.css.

catalog.section — обёртка на .catalog--item вокруг .product-card. Пример был выше.

sale.basket — обёртка на .basket--item вокруг строки корзины. На широком экране строка таблицы, на узком — стопка блоков, и переключение делает @container вместо медиа-запроса.

<div class="basket--list">
    <?php foreach ($arResult['BASKET_ITEMS'] as $arItem): ?>
        <div class="basket--item">
            <div class="basket-row">
                <div class="basket-row--name"><?=htmlspecialcharsbx($arItem['NAME'])?></div>
                <div class="basket-row--price"><?=htmlspecialcharsbx($arItem['PRICE_FORMATED'])?></div>
                <div class="basket-row--quantity"><?=htmlspecialcharsbx($arItem['QUANTITY'])?></div>
            </div>
        </div>
    <?php endforeach; ?>
</div>

news.list — обёртка на .news--item вокруг карточки новости. В широком списке карточка горизонтальная с картинкой слева, в узком — вертикальная с картинкой сверху. Разметка та же, стили в компонентном style.css.

Чистый template.php без JS-костылей

Раньше, чтобы переключить карточку из горизонтальной в вертикальную при переносе в слайдер, приходилось либо дублировать шаблон, либо писать JS, который через ResizeObserver измерял ширину родителя и вешал класс .is-narrow. Теперь этого не нужно.

В template.php остаётся только разметка. Никаких проверок ширины, никаких условных классов. Стили компонента — в style.css, который Bitrix подключает автоматически, если он есть в папке шаблона компонента. Никаких инлайновых стилей, никаких прямых <link> и <script> — только штатные механизмы Bitrix.

Часть 4. Тестирование

Container Queries ломаются тихо: страница выглядит нормально на широком экране, а в узком сайдбаре внезапно разъезжается. Проверять нужно каждое место, где компонент реально живёт.

DevTools

В Chrome DevTools есть отдельная панель для контейнеров. Открывается через Elements → Layout. Включите отображение контейнеров — инспектор подсветит все элементы с container-type и покажет их имена. Если контейнер не подсвечивается, значит container-type не применился: скорее всего, элемент схлопнулся или стиль перебит.

Через Elements → Styles можно временно изменить ширину контейнера вручную: правый клик на элементе → Edit as HTML или прямое редактирование style="width: 300px". Это быстрее, чем тянуть окно браузера туда-сюда.

Как проверить карточку в четырёх контекстах

  1. Сетка каталога. Открыть /catalog/, уменьшить окно до 320px, убедиться, что карточка вертикальная и ничего не вылезает за контейнер.
  2. Слайдер. Открыть страницу с блоком «Вы смотрели» или похожим, проверить, что ячейки слайдера скроллятся, а карточки внутри остаются вертикальными.
  3. Сайдбар. Открыть страницу с боковой колонкой, где используется тот же компонент. Здесь карточка может быть горизонтальной при широком вьюпорте, но в узком сайдбаре должна быть вертикальной. Если она горизонтальная — контейнер стоит не там, где нужно.
  4. Модальное окно. Если карточка открывается в модалке (например, «Быстрый просмотр»), её ширина обычно 600–800px, но окно может быть ресайзибельными. Проверить, что запросы срабатывают относительно модалки, а не страницы под ней.

Эмуляция медленных устройств и SPA-переходов

В DevTools есть режим Rendering → Emulate CSS media feature prefers-reduced-motion и другие. Полезно проверять поведение при prefers-reduced-motion: reduce, чтобы анимации внутри контейнера не ломали ожидания пользователя.

Если сайт работает как SPA или использует динамическую подгрузку (например, через AJAX в Bitrix), обязательно проверяется перемонтирование компонента. При переходе между страницами контейнеры должны создаваться заново, а старые MutationObserver и ResizeObserver — отключаться. Проверить это можно во вкладке Performance: если количество observers растёт с каждой навигацией — утечка.

Чек-лист внедрения

  • Объявить глобальные CSS-переменные для clamp() в template_styles.css шаблона сайта.
  • Перевести типографику и отступы на жидкие значения — сначала в шаблоне, потом в компонентах.
  • Скопировать нужные шаблоны компонентов в /local/templates/<шаблон>/components/ перед правкой.
  • Для каждого переиспользуемого компонента добавить обёртку на элемент и повесить на неё container-type: inline-size с осмысленным container-name.
  • Писать @container от имени контейнера, а не безымянно, если внутри уже есть другие контейнеры.
  • Использовать cqi/cqw для жидких размеров внутри компонента вместо vw.
  • Обернуть все контейнерные правила в @supports (container-type: inline-size) вместе с медиа-запросным fallback.
  • Медиа-запросы оставить только для структурных изменений: скрыть сайдбар, переключить меню, изменить порядок блоков.
  • Проверить компонент в четырёх контекстах: сетка, слайдер, сайдбар, модальное окно.
  • Убедиться, что количество контейнеров не избыточно, и что внутри них нет position: fixed.

Медиа-запросы не исчезнут полностью. Но их станет на порядок меньше. А компоненты перестанут ломаться при переносе из одного места в другое — и это главное, что даёт переход на clamp() и Container Queries.

Александр Тихий
Автор статьи

Александр Тихий

Fullstack-разработчик · 1С-Битрикс

Разрабатываю и развиваю интернет-магазины и корпоративные порталы на 1С-Битрикс. Интеграции с 1С, highload-нагрузки, безопасность по 152-ФЗ.


Комментарии

Комментариев еще нет, Вы можете стать первым кто его оставит

Оставьте комментарий

На сайте используется система премодерирования комментариев, поэтому ваше сообщение будет опубликовано лишь после одобрения модератором

Вы отвечаете на комментарий пользователя

Отправить

ОБРАТНАЯ СВЯЗЬ

Напишите мне

Напишите мне, чтобы обсудить задачу. Работаю удаленно, официально (самозанятый), стоимость часа — 1800 ₽, в день могу уделять проекту 3–4 часа. Отвечаю быстро, консультация бесплатная.

Во время отправки произошла ошибка, пожалуйста попробуйте еще раз через некоторое время
Сообщение отправлено успешно

Телефоны

+7(993) 007-18-96

Email

info@tichiy.ru

Адрес

Россия, г. Москва

Отправляя форму Вы автоматически подтверждаете, что ознакомились и принимаете Политику конфиденциальности сайта