Нетривиальная расстановка элементов на flexbox без media-запросов
Содержание:
min-width имеет значение
Возможно, ты думаешь, что несложно заставить все flex-элементы внутри flex-контейнера сжиматься, для того чтобы уместить контент. Наверняка, если ты укажешь flex-shrink: 1 на элементах, они так и будут себя вести, правда?
Может, пример.
Скажем, у тебя есть часть DOM, которая отображает книгу на продажу и кнопку чтобы ее купить.
Ты разместил все с помощью flexbox и все хорошо.
(Поскольку ты хочешь кнопку «Купить» справа — даже для очень коротких названий — ты, будучи умным, указал margin-left: auto)
Название книги довольно длинное, поэтому оно использует столько пространства сколько может и затем переходит на следующую строку. Ты счастлив, жизнь прекрасна. Ты блаженно отправляешь свой код в продакшн, с уверенностью, что он выдержит все.
И потом получаешь неприятный сюрприз. Совсем не хорошего рода.
Некий дурень, много о себе возомнивший, написал книгу с длинным словом в названии.
Все сломано!
Если красная граница обозначает ширину смартфона, и ты скрываешь переполнение (overflow: hidden), ты только что потерял свою кнопку «Купить». Твой коэффициент конверсии — как и эго бедного автора — будет страдать.
(Примечание: к счастью, там где я работаю, есть хорошая QA команда, которая наполнила нашу базу данных разнородным текстом, наподобие такого. В частности, именно эта проблема побудила меня прочитать спецификацию.)
Оказывается, такое поведение происходит из-за того, что min-width элемента описания изначально установлена в auto, что в данном случае равняется ширине слова Electroencephalographically (электроэнцефалографически). Flex-элементу буквально не разрешается быть уже чем это слово.
Решение? Переопределить эту проблемную минимальную ширину min-width: auto установив min-width: 0, указывая flexbox’у, что этот элемент может быть уже, чем содержимое внутри него.
Теперь за управление текстом внутри элемента отвечаешь ты. Я предлагаю перенести слово. Таким образом, твой CSS будет выглядеть так:
Результат будет таким:
Опять же, min-width: 0 не какой-то хак для обхода нелепости, это .
В следующем разделе, я вернусь к тому, что кнопка «Купить» совсем не 80 пикселей по ширине, как я довольно ясно ей сказал.
Пример 3: Как сделать макет сайта, используя Флексбокс
Строительство макетов полностью на Флексбокс не особо одобряется сообществом разработчиков. И, разделяя данное мнение, я все же считаю, что бывают ситуации, когда это допустимо. Самый главный совет, который я могу вам дать:Используйте флексбокс, когда это имеет смысл. Я объясню это на следующем примере.
Макет сайта “святой Грааль”
Самый наистандартнейший макет страницы на свете
Макет “святой Грааль” – хэдер, футер и 3 контейнера для контента
Есть два способа попытаться построить этот макет с помощью Flexbox. Начнем с первого. Для него нужно разместить во флекс-контейнере header, footer, nav, article и aside.
Разметка
Так выглядит наша разметка:
<body> <header>Header</header> <main> <article>Article</article> <nav>Nav</nav> <aside>Aside</aside> </main> <footer>Footer</footer> </body>
Среди прочих, в стандартнейшей разметке есть особое правило: центральная колонка, article в разметке должна идти перед обоими сайдбарами nav и aside.
Article должен идти в разметке первым, но располагаться по центру макета
Подключаем флексбокс
body { display: flex }
Поскольку дочерние элементы должны идти сверху вниз, изменим стандартное направление флексбокс
body { ... flex-direction: column }
- header и footer должны быть фиксированной ширины
header, footer { height: 20vh /*you can use pixels e.g. 200px*/ }
- main должен занимать все свободное пространство в контейнере
main { flex: 1 }
Надеюсь, вы помните, что запись flex: 1 означает тоже самое что и flex-grow: 1, flex-shrink: 1 и flex-basis: 0
Это приведет к тому, что main вырастет и займет все доступное ему место
На этом этапе необходимо позаботиться о содержимом main – блоках article, nav и aside. Сделаем main флекс-контейнером
main { display: flex }
А для nav и aside установим значение width
nav, aside { width: 20vw }
Убедимся, что article занимает все доступное ему пространство
article { flex: 1 }
Теперь article занимает все свободное место
Осталось сделать всего одну вещь. Поменяем значения flex-order, чтобы nav отображался первым
nav { order: -1 }
Готовый вариант
Свойство order используется, чтобы переопределить порядок flex-items. Все элементы flex-items внутри контейнера отображаются в порядке возрастания значения order. Элемент с наименьшим значением будет отображаться первым. По умолчанию значение order для всех flex-items равно 0.
Второе решение для макета
Предыдущее решение использует flex-container для всего контейнера. Макет очень сильно зависит от flexbox. Посмотрим на более разумный подход. Еще раз взглянем на результат, который должен у нас получиться.
Макет “святой Грааль”
header и footer могут быть блочными элементами. Без лишних вмешательств они и так заполнят все доступное им простанство контейнера и будут прижаты к верху и низу
<body> <header>Header</header> <main> <article>Article</article> <nav>Nav</nav> <aside>Aside</aside> </main> <footer>Footer</footer> </body>
Что означает, что флекс-контейнер необходим только для main. Единственная сложность здесь заключается в том, что вам необходимо самим вычислить высоту блока main. Он должен занимать все свободное пространство между header и footer
main { height: calc(100vh - 40vh); }
Рассмотрим этот код. Он использует CSS функцию calc для того, чтобы вычислить высоту main. Высота блока должна быть равна calc (100vh – высота хэдера – высота футера). В предыдущем случае вы должны были задать фиксированную высоту футеру и хэдеру. Теперь вы поступаете таким же образом только с main.Здесьлежит готовый результат.
Макет сайта в 2 колонки
Двухколоночный макет очень распространен. Их тоже очень легко строить на флексбокс.
Макет сайта в две колонки (сайдбар и основной контент)
Вот наша верстка:
<body> <aside>sidebar</aside> <main>main</main> </body>
Инициализируем флексбокс
body { display: flex; }
Задаем блоку aside фиксированную ширину
aside { width: 20vw }
И, наконец, убедимся, что main занимает все доступное пространство
main { flex: 1 }
Вот, в общем-то, и все, что нужно сделать.
Реальные примеры
Применяя описанные выше свойства flexbox в различных комбинациях, можно создавать разнообразные шаблоны. Рассмотрим примеры использования Flexbox.
Меню навигации
Основное преимущество CSS flex заключается в том, что элементы могут адаптироваться. Когда размеры экрана изменяются, flexbox изменяет ширину блоков, чтобы они соответствовали родительскому контейнеру. Данная технология использует процентное значение размеров по отношению к родительскому контейнеру, что и позволяет элементам навигации легко адаптироваться к размеру экрана.
Очень просто перейти к размерам на всю ширину экрана устройства, изменив способ, с помощью которого flexbox реагирует на изменения.
Посмотрите, как в приведенном выше примере элементы реагируют на различные размеры экрана. Ниже приведен код HTML и CSS, с помощью которых можно создать адаптивное меню навигации с использованием flexbox:
<nav class="site-navigation"> <ul> <li><a href="">Home</a></li> <li><a href="">Services</a></li> <li><a href="">Products</a></li> <li><a href="">About</a></li> <li><a href="">Contact</a></li> </ul> </nav> .site-navigation ul { background: #eee; list-style: none; margin: 0; padding: 0; /** * Flexbox properties */ display: flex; justify-content: space-around; } .site-navigation a { color: #333; display: block; text-decoration: none; text-align: center; padding: 1rem; } .site-navigation a:hover { background: #d4d4d4; } @media all and (max-width: 600px) { .site-navigation ul { /** * Full width navigation items */ flex-flow: column wrap; padding: 0; } }
Столбцы одинаковой высоты
Вы можете оказаться в ситуации, когда столбец основного контента становится больше, чем столбец боковой панели. Это может привести к проблемам с отображением, если боковая панель имеет свой фоновый цвет.
Посмотрите, как можно создать столбцы одинаковой высоты с помощью CSS flex 1.
Код HTML и CSS, с помощью которых можно создать такой макет:
<div class="column-container"> <div class="column"> <p></p> <p></p> </div> <div class="column"> <p></p> </div> <div class="column"> <p></p> </div> </div> .column-container { display: flex; align-items: stretch; } .column { width: 33%; padding: 2rem; } .column:nth-child(1) { background: red; } .column:nth-child(2) { background: blue; } .column:nth-child(3) { background: green; }
В этом коде CSS единственным свойством, которое нужно задать для получения одинаковых столбцов, является align-items: stretch:
.column-container { display: flex; align-items: stretch; }
Центрирование по вертикали
Получить элемент, выровненный вертикально по центру внутри родительского элемента, ранее было непростой задачей. Это проще было сделать с помощью переходов и абсолютного позиционирования:
.vertically-align-center-child { top: 50%; transform: translateY(-50%); }
Но с помощью flexbox это делается еще проще. Для этого используются два свойства CSS flex1:justify-content и align-items.
<div class="vertical-container"> <div class="vertical-content">Look I'm Vertically Aligned</div> </div> .vertical-container { background:#eee; height: 500px; /** make it flex */ display: flex; /** Vertically center */ align-items: center; /** Horizontally center */ justify-content: center; } .vertical-content { background: #FFF; padding: 3rem; width: 20%; text-align: center; }
Изменение порядка вывода элементов с помощью медиа-запросов
Допустим, у вас есть макет страницы с заголовком, левой боковой панелью, основным контентом, правой боковой панелью и подвалом. Если при разработке мобильной версии ресурса мы зададим отображение всех разделов в полную ширину, то левая боковая панель может выводиться сверху от блока основного контента.
С помощью display flex CSS мы можем изменить порядок вывода различных разделов. Можно переместить блок основного контента перед левым сайдбаром.
Чтобы изменить порядок вывода дочерних элементов, нужно добавить для элемента свойство order и указать, на какой позиции он должен отображаться:
@media only screen and (max-width: 320px) { .site-header { order: 2; } .main-content { order: 1; width: 100%; } .left-sidebar { order: 4; width: 100%; } .right-sidebar { order: 3; width: 100%; } .site-footer { order: 5; } }
Теперь порядок размещения будет следующим:
- Основной контент;
- Заголовок;
- Правая боковая панель;
- Левая боковая панель;
- Подвал.
Просмотрите приведенную ниже демо-версию. Измените размеры окна браузера, чтобы увидеть, как меняются местами области страницы.
Обработка размеров flex-элемента
Теперь, когда мы определили некоторые термины, мы можем посмотреть, как наши flex-элементы рассчитывают размер. Начальные значения flex-свойств выглядят следующим образом:
- flex-grow: 0;
- flex-shrink: 1;
- flex-basis: auto.
flex-basis это база, от которой рассчитывается размер. Если мы установим flex-basis равным 0, а flex-grow равным 1, то все наши элементы не будут иметь начальной ширины, поэтому пространство во flex-контейнере будет распределено равномерно, назначив одинаковый размер пространства для каждого элемента.
Между тем, если flex-basis установить в auto а flex-grow: 1, то будет распределено только свободное пространство, т.е. пространство без контента.
В ситуации, когда нет свободного места, например, когда у нас контента больше, чем может поместиться в одной строке, тогда ничего не распределяется.
Это показывает нам, что выяснение того, что означает auto, очень важно, если мы хотим знать, как Flexbox обрабатывает размеры наших элементов. Значение auto будет нашей отправной точкой
Определение auto (defining auto)
Когда auto назначается как значение чего-нибудь в CSS, оно будет иметь очень специфическое значение в этом контексте, которое стоит посмотреть. Рабочая группа CSS тратит много времени на выяснение того, что означает auto в любом контексте, как объясняет этот разговор с редактором спецификаций Fantasai.
В спецификации мы можем найти информацию о том, что означает auto при использовании в качестве flex-basis. Термины, определенные выше, должны помочь нам проанализировать это утверждение.
Таким образом, если наш flex-basis установлен в auto, Flexbox просмотрит значение свойства main size. Мы должны иметь main size, если мы дали одному из наших flex-элементов ширину. В примере ниже, все элементы имеют ширину 110px, поэтому это значение используется в качестве main size т.к. начальное значение flex-basis — auto.
Однако в нашем первоначальном примере есть элементы, у которых нет ширины, это означает, что их main size — auto, и поэтому нам нужно перейти к рассмотрению следующего высказывания: “если это значение само по себе auto, то используется значение content.”
Теперь нам нужно посмотреть, что говорит спецификация о ключевом слове content. Это еще одно значение, которое вы можете использовать (при поддержке браузеров) для свойства flex-basis, например:
Спецификация определяет content следующим образом:
В нашем примере с flex-элементами, содержащими текст, мы можем игнорировать некоторые более сложные настройки и рассматривать content как размер max-content.
Это объясняет, почему, когда у нас есть небольшое количество текста в каждом элементе, текст не переносится. flex-элементы по умолчанию имеют auto размер, поэтому Flexbox берет их размер в свойстве max-content, элементы помещаются в контейнер такого размера, и работа выполнена!
На этом история не заканчивается, так как когда мы добавляем еще контент, элементы не остаются в размере max-content. Если бы они это делали, то вырвались бы из flex-контейнера и вызвали бы переполнение. Как только они заполнят контейнер, содержимое начинает переноситься, и элементы становятся разных размеров, основываясь на содержимом внутри них.
justify-content
Copied!
Copied!
Copied!
Copied!
Copied!
Copied!
Copied!
Это свойство выравнивает сетку вдоль оси строки (в отличии от свойства align-content, которое выравнивает сетку вдоль оси столбца)
Наследуется: нет.
Применяется к: block контейнерам, flex контейнерам и grid контейнерам.
Значение по умолчанию: normal.
- start
- выравнивает сетку по левой стороне контейнера.
- end
- выравнивает сетку по правой стороне контейнера.
- center
- выравнивает сетку по центру контейнера.
- stretch
- масштабирует элементы чтобы сетка могла заполнить всю ширину контейнера.
- space-around
- одинаковое пространство между элементами, и полуразмерные отступы по краям.
- space-between
- одинаковое пространство между элементами, без отступов по краям.
- space-evenly
- одинаковое пространство между элементами, и полноразмерные отступы по краям.
Опыт веб-студии ITSOFT
Мы в веб-студии ITSOFT перешли на Flex в 2010 году. В основе всех наших новых проектов лежит именно эта технология. Наш опыт показал, что она позволяет создавать адаптивные и кроссбраузерные сайты с действительно красивым дизайном.
При использовании Flex нужно учитывать, что:
-
Flex-элементы по умолчанию ужимаются под свое содержимое; Это может пригодиться, когда есть блоки, размер которых изначально неизвестен и зависит от количества контента.
Примеры: пункты меню в https://ketoplus.ru/
-
Внешние отступы flex-элементов не схлопываются и не выпадают, в отличие от блочной модели.
Схлопывание и выпадание отступов полезно, в основном, при верстке текстовых страниц, поэтому во избежание путаницы в отступах при создании сеток отсутствие такого поведения приходится очень кстати.
Пример: блоки в http://velpharm.ru/about/veltrade/
-
Flex-элементы умеют перераспределять свободное пространство вокруг себя, таким образом меняя свои размеры;
Больше не нужно вручную задавать ширину в процентах флекс-элементам, если необходимо равномерно заполнить все пространство флекс-контейнера. Браузер сам рассчитает размеры и распределит элементы по флекс-контейнеру.
Пример: главная страница http://oflomil.ru/
-
Внутри одного флекс-контейнера можно менять порядок флекс-элементов, хотя в DOM-дереве порядок остается неизменным.
Бывают макеты страниц, в которых порядок следования элементов отличается на мобильной и десктопной версиях. Flex справится с задачей.
Пример: разный порядок следования логотипа и навигации в шапке в мобильной и десктопной версиях (http://elmucin.ru/).
-
Flex-элементу можно задать не только горизонтальные автоматические отступы, но и вертикальные; к тому же есть специальные свойства, с помощью которых очень просто выравнивать элементы внутри флекс-контейнера по горизонтали или вертикали.
Пример: кнопка всегда находится в нижней части карточки статьи (https://rabiet.ru/experts/), блок продукция (https://stomatofit.ru/#products).
-
Flex-элементы могут переноситься на следующую строку, если указано соответствующее свойство.
Эта особенность полезна в каталогах и различных списках, где изначально количество всех элементов неизвестно. Если их станет слишком много и предусмотрен перенос, то страница в этом случае не развалится.
Пример: каталог Велфарм (http://velpharm.ru/catalog/), блок Где купить (http://valosemid/#partners, https://gopantomid.ru/)
Стоит отметить, что Flexbox поддерживается в Internet Explorer 10-11, хоть и с некоторыми оговорками.
Некоторые интересные фишки Flex мы реализовали на сайте oflomil.ru. На разводящей странице есть 3 столбца на всю высоту видимой области экрана. На мобильном они трансформируются в 3 строки, каждая из которых равномерно занимает место в видимой части экрана. На продуктовых страницах без единого скрипта реализована бегущая строка. Текстовые элементы расположены в ряд благодаря inline-flex. Все свободное пространство в ряду распределено между этими элементами равномерно. Наш собственный сайт также свёрстан с использованием Flex.
Реализация бегущей строки с Flex
Из недостатков можно отметить то, что Flex не хватает при верстке писем. Не во всех почтовых клиентах он работает корректно.
В скором времени большую распространённость получит технология Grid. Однако Grid не замена Flexbox. Флексы в связке с гридами помогут решать задачи, которые раньше были сложными или вовсе невозможными. К примеру, Masonry-раскладка — одна из тех вещей, которую нельзя полноценно реализовать на данный момент. После появления возможностей спецификации Grid Layout 3 уровня в браузерах, реализация такой раскладки станет возможной и к тому же простой.
Дата-центр ITSOFT — размещение и аренда серверов и стоек в двух дата-центрах в Москве. За последние годы UPTIME 100%. Размещение GPU-ферм и ASIC-майнеров, аренда GPU-серверов, лицензии связи, SSL-сертификаты, администрирование серверов и поддержка сайтов.
Justify Content
Свойство определяет горизонтальное положение элементов. Это свойство похоже на Flex Wrap, но в justify сохраняется первоначальный порядок элементов.
В следующем примере () все элементы вне зависимости от их ширины имеют горизонтальное позиционирование по центру родительского контейнера. Это похоже на свойства .
Значение добавляет пробелы между всеми inner-элементами, тем самым растягивая строку на всю ширину контейнера:
На первый взгляд следующий пример может показаться идентичным примеру выше. Разница между ними хорошо видна, если элементов будет не целый алфавит, а всего несколько. В следующем примере появляются внешние отступы у крайних нижних элементов.
Пример выше со значением не имеет отступов на угловых элементах. Пример ниже со значением делает равные внешние отступы на всех элементах.
Идентичный прошлому пример с растянутым элементом middle:
Как видите, вам всё равно придётся экспериментировать с flex-элементами, чтобы достичь правильного результата именно для вашего случая. Результат, естественно, зависит и от размеров содержимого.
align-self
Применяется к дочерним элементам. Позволяет переопределить выравнивание, заданное в align-items для отдельных элементов.
Все возможные значения для свойства:
- flex-start: граница cross-start для элементов располагается на позиции cross-start
- flex-end: граница cross-end для элементов располагается на позиции cross-end
- center: элементы выравниваются по центру поперечной оси
- baseline: элементы выравниваются по своей базовой линии
- stretch (по умолчанию): элементы растягиваютcя, заполняя контейнер (с учётом min-width/max-width)
Обновим стили. Зададим другое выравнивание первому элементу:
.parent { displayflex; border2px solid #FF8C00; padding20px; width760px; align-itemscenter; height300px; } .child { background-color#ededed; border2px solid #768D44; padding30px; margin10px; } .child:first-child { align-self:flex-start; }
В приведенном примере — первый блок находится в начале родительского, а второй и третий выравнены по центру.
Ну и в заключение приведу пример, в которой в строку будут стоят 3 блока. Первый блок будет 200px, сжиматься и растягиваться не будет. Остальные 2 блока будут занимать все оставшееся пространство, причем как растягиваться так и сжиматься. Без flexbox это сделать достаточно проблематично. Посмотрим на код css при использовании flexbox:
.parent { displayflex; border2px solid #FF8C00; padding20px; width760px; } .child { background-color#ededed; border2px solid #768D44; padding30px; margin10px; flex1 200px; } .child:first-child { flex 200px; }
Вот и все! Обзорная экскурсия по flexbox закончена. Экспериментируйте и все получится!
Что такое Flexbox?
Flexbox – это режим разметки, созданный для упорядочения элементов на странице таким образом, чтобы они вели себя предсказуемо для случаев адаптивности страницы под различные размеры экрана и для различных устройств.
Используя flexbox, контейнер и его дочерние элементы могут быть расположены в любом направлении: влево, вправо и даже вверх или вниз. Вы можете выбрать нужный порядок элементов на странице и упорядочить их, выровнять содержимое по ширине справа налево с помощью одного свойства, и даже добавить любое количество столбцов в разметку страницы своего сайта. Размер блоков также является гибким, поскольку элементы могут увеличиваться, чтобы занять неиспользуемое пространство или сжиматься, чтобы не допустить переполнения.
На данный момент flexbox поддерживается практически всеми современными браузерами, включая Android и iOS.
Когда использовать Flexbox при верстке макета
В одной из предыдущих статей мы писали об использовании сеток в качестве метода для респонсивного дизайна. Хотя с помощью Flexbox технически можно сверстать полный макет для сайта, он не предназначен исключительно для этой цели. Скорее, он лучше подходит для стилизации отдельных контейнеров, таких как контейнер основного контента, боковая панель (сайдбар), хедер и другие подобные разделы. Все же сетки лучше подходят для создания всего макета.
Разница заключается в том, как flexbox взаимодействует с браузерами, в которых загрузка страницы происходит постепенно. Сначала контент растягивается горизонтально, чтобы заполнить весь экран. По мере загрузки всех остальных контейнеров горизонтальное отображение динамически настраивается и сжимается для заполнения всей ширины экрана, чтобы включить окружающие элементы.
Другими словами пользователь на доли секунды увидит совсем не тот макет, который планировался. Но после полной загрузки страницы все, конечно же, выравнивается.
Контейнеры, дочерние элементы и Flex
Прежде чем мы начнем писать код CSS с использованием flexbox, есть некоторые важные концепции, с которыми в первую очередь нужно ознакомиться:
- flexbox – контейнер становится flexbox после того, как подключается свойство со значением или
- flex item – дочерний элемент в flexbox
- главная ось (main axis) – это основная ось, вдоль которой выравниваются элементы
- перекрестная ось (cross axis) – ось, перпендикулярная главной оси. Также называется поперечной осью
- главное начало/главный конец (main-start/main-end) – флекс элементы помещаются в контейнер, который начинается со стороны главного начала, и заканчивается к главному концу
- перекрестное начало и конец (cross start/end) – флекс линии заполняются items (элементами) и помещаются в контейнер, который начинается со стороны перекрестного начала флекс контейнера и идет к перекрестному концу
- свойство основного размера (main size) – ширина или высота флекс элемента, в зависимости от того, что находится в основном измерении главной оси, является основным размером элемента. Свойство основного размера элемента flex – это свойство ширины или высоты, в зависимости от того, что находится в основном измерении
- свойство перекрестного размера (cross size) – ширина или высота флекс элемента, в зависимости от того, что находится в поперечной оси измерении, является перекрестным размером элемента. Свойство перекрестного размера зависит от ширины или высоты, которое находится в поперечном измерении
Графическое описание важных концепций для flexbox в CSS3
В CSS есть определенные свойства, на которые не влияет свойство flexbox, поскольку они фактически не делают контейнеры блоками:
column-* float clear vertical-align ::first-line и ::first-letter
Создание HTML5 контейнера
Теперь мы можем начать строить макет, используя flexbox. Для этого создайте костяк html-страницы (или же в php, если вы используете CMS).
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Заголовок страницы</title> </head> <body> </body> </html>
Создайте родительский контейнер внутри :
<div class="content"> </div>
Внутри этого контейнера вы можете добавить любой контент.
В качестве теста я создам три блока с небольшой информацией, и блок с основным контентом под ними.
<div class="content"> <div class="blok">Блок информации №1</div> <div class="blok">Блок информации №2</div> <div class="blok">Блок информации №3</div> <article>Здесь основной контент.</article> </div>
Теперь, чтобы придать этому костяку некоторых красок, добавим несколько основных стилей CSS (вы можете это сделать с помощью отдельного подключаемого файла css стилей, или же включить эти стили в тег в разделе ).