Респонсивная раскладка без медиа-запросов
Допустим, у нас классический случай: сайдбар и область с основным контентом. Как мы раньше верстали такую конструкцию? Задавали им ширину и ставили рядом с помощью float. А потом на необходимом размере убирали float:
@media (max-width: 20rem) { .sidebar, .main-content { width: 100%; float: none; }}
А теперь сделаем то же самое на флексах и избавимся от медиа-запроса. Для начала откажемся от размеров и примем, что ширина сайдбара должна быть не менее 300px, а ширина блока с основным контентом — не менее 60% родительского элемента:
.section { /* родительский блок */ display: flex; flex-wrap: wrap;}.main-content { min-width: 60%;}.sidebar { flex-basis: 300px;}
Теперь нам нужно быть уверенными, что сайдбар и основной контент получат необходимую ширину, а если поставить их друг под друга, то займут всю доступную ширину. Поэтому для сайдбара мы пропишем flex-grow: 1;
, а для основного контента — flex-grow: 9999;
. Откуда 9999? Всё очень просто. Если мы напишем основному контенту flex-grow: 1;
, то в итоге его ширина будет 60% от родителя, а остальное место займёт сайдбар, у которого тоже flex-grow: 1;
. Но нам же нужно, чтобы ширина сайдабара была только 300px. И здесь полезно вспомнить как вообще работает flex-grow. Он делит между элементами, для которых он указан, свободное место, оставшееся после определения размеров и размещения всех остальных элементов внутри флекс-контейнера. Допустим, у нас остаётся свободными 100px. Для одного элемента мы указываем flex-grow: 1;
, а для другого flex-grow: 3
. Это означает, что первый элемент получит 1/4 от 100px (25px), а второй — 3/4(75px). Теперь понятнее, да? Когда мы указываем для основного контента flex-grow: 9999;
, то сайдбар со своим flex-grow: 1;
получает всего лишь 1/10000, что браузер округляет до 0. И так мы получаем необходимые размеры.
Полный код примера:
.section { display: flex; flex-wrap: wrap;}.main-content { min-width: 60%; flex-grow: 9999;}.sidebar { flex-basis: 300px; flex-grow: 1;}
А что делать, если нужно, чтобы между сайдбаром и основным контентом был отступ? Очень просто: добавить margin
сайдбару и основному контенту и компенсировать его у родителя:
.section { margin: -0.5rem; display: flex; flex-wrap: wrap;}.main-content { margin: 0.5rem; min-width: 60%; flex-grow: 9999;}.sidebar { margin: 0.5rem; flex-basis: 300px; flex-grow: 1;}
И ещё одно а что. А что, если нужно сделать респонсивную сетку для множества элементов, типа каталога? Тут во всей красе раскрывается grid. Достаточно всего пары строк кода:
.grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr)); grid-gap: 1rem;}
Вот так просто. Никаких лишних телодвижений, никаких заморочек с медиа-запросами. Просто работает.
Кстати, эти примеры отлично отвечают на вопрос «Что лучше использовать, гриды или флексы?». Он в корне неверен. Не нужно выбирать что-то одно. Гриды не заменяют флексы. Их прекрасно можно использовать совместно. Можно общую раскладку сделать по вышеуказанному методу на флексах, а внутри блока с основным контентом для сетки использовать гриды. Выбирайте инструменты исходя из задачи.