После того как я погрузился в возможности container queries, container units, а также fluid-типографику с clamp() и minmax(), возник вопрос: а можно ли вообще избавиться от флагов, пропсов и хуков в React-компонентах, которые отвечают за адаптивность?
Зачем каждый раз писать isMobile, size, compact, dense, fullWidth, вызывать хук для определения ширины экрана, если можно описать поведение компонента сразу через CSS и дать ему возможность адаптироваться к размеру своего контейнера?
Это размышление постараюсь разбить в небольшую серию постов, где я исследую, как убрать всю эту логику из JS и сделать компоненты по-настоящему контекстными и адаптивными.
Вот с чего обычно всё начинается:
`function ProductCard({ product, isMobile }) { return (
{product.name} {!isMobile && {product.description}} {product.price} Купить
); } К чему хочется прийти (css modules не обязательно, будем пробовать tailwind-variants, headless решения, какой-нибудь react-aria-components)
function ProductCard({ product }) {
return (
{product.name}
{product.description}
{product.price}
Купить
);
}
**Почему нам нужны новые подходы к адаптивному дизайну**
В мире веб-разработки адаптивный дизайн всегда был ключевым аспектом создания качественных пользовательских интерфейсов. Долгое время мы полагались на медиа-запросы, привязанные к размеру экрана:
`/* Традиционный подход с медиа-запросами */
@media (max-width: 768px) {
.card {
flex-direction: column;
}
}
Этот подход привел к появлению условных конструкций в коде компонентов:
`Нажми меня
Хотя медиа-запросы решали многие проблемы, они имеют существенный недостаток: компоненты реагируют только на размер экрана, а не на контекст, в котором они используются. Но что, если компоненты могли бы адаптироваться к размеру своего непосредственного контейнера?
Если схематично представить, то получается так, что вписываем наши компоненты в рамки и от их размеров этот компонент сам будет меняться
0px 350px 500px
│─────────│────────────│
│ ┌────────────────────────────┐
│ │ ┌──────┐ Address │
│ │ │ IMG │ $280k–$310k │
│ │ └──────┘ [Confidence: 85%] │
│ └────────────────────────────┘
0px 350px
│─────────│
│ ┌────────────────────────────┐
│ │ ┌────────────┐ │
│ │ │ IMAGE │ │
│ │ └────────────┘ │
│ │ 123 Main St, Phoenix AZ │
│ │ $280,000 – $310,000 │
│ │ [Confidence score: 85%] │
│ └────────────────────────────┘
Далее это вижу так: любой шаблон, макет, layout — это всегда набор блоков, в которые помещаются элементы интерфейса и контент.
Возьмём лист А4 — у него фиксированная ширина, но внутри этой ограниченной области мы можем располагать элементы, считая, что доступная ширина — 100%. Аналогично с экранами устройств: у каждого девайса своя фиксированная ширина в пикселях, но с точки зрения CSS мы всё равно часто оперируем значением width: 100%.
Контент всегда занимает доступную ширину родителя. Один блок вкладывается в другой, и относительные значения продолжают работать — 100% внутри 100%, но в пикселях это уже конкретные числа, зависящие от контекста.
Это база (пересказал css): любой layout строится из вложенных прямоугольников с фиксированной пиксельной шириной, даже если мы пишем width: 100%.```