Какой самый лучший способ понять Flexbox? Изучить основы и написать кучу разных штук. Именно этим мы и займемся.

Но сначала стоит кое-что уточнить:

  • Эта статья написана для разработчиков среднего уровня и предполагает, что вы уже имеете представление о Флексбоксах. Но…
  • Если вы в курсе, что такое CSS, но не имели дела с Флексбокс, то здесь находится исчерпывающий гид по технологии (статья в открытом доступе, необходимо, примерно, 45 минут на чтение).
  • А если вы не особо хороши в CSS, то я рекомендую вам Полное (Практическое) введение в CSS (платный курс, 74 лекции, английский язык).
  • Примеры из статьи можно реализовывать в произвольном порядке.
  • Флексбокс – всего лишь технология разметки. Реальные проекты одной только разметкой не ограничиваются.
  • Обозначения типа div.ohans означают что это элемент div с классом ohans.

Пример 1. Как сделать фотогалерею на Флексбокс

Разместить фотографии по строкам и столбцам на Флексбокс гораздо проще, чем многим кажется.
Рассмотрим простую сетку:

<main class="gallery">
 
  <img src="/sample.jpg">
 
  <img src="/sample.jpg">
 
  <img src="/sample.jpg">
 
  <img src="/sample.jpg">
 
  <img src="/sample.jpg">
 
  <img src="/sample.jpg">
 
  <img src="/sample.jpg">
 
  <img src="/sample.jpg">
 
  <img src="/sample.jpg">
 
  <img src="/sample.jpg">
 
</main>

У нас есть main.gallery и 10 изображений в нем.
Убедимся, что main.gallery растягивается на весь доступный экран:

.gallery {
 
   min-height: 100vh
 
}

Кое-что об изображениях

По умолчанию все изображения inline-block элементы. У них есть ширина и высота. Они выстроятся в линию (только если они не слишком большие и могут все поместиться)

На старт

Сейчас наша галерея будет выглядеть следующим образом:

Размеры всех 10 изображений остались нетронутыми. При необходимости картинки переместятся на вторую строку. Послушные ребята =)

Размеры всех 10 изображений остались нетронутыми. При необходимости картинки переместятся на вторую строку. Послушные ребята =)

А теперь, на сцену выходит Флексбокс:

.gallery {
 
    display: flex
 
 }

С этого момента поведение изображений изменилось. Из inline-block элементов они стали flex-items.
В результате применения Флексбокс к .gallery все картинки уместились в одну линию. Да еще и растянулись по вертикали, вот так:

Картинки теперь уместились все в одну линию, да еще и растянулись по вертикали. Жалкое зрелище =(

Картинки теперь уместились все в одну линию, да еще и растянулись по вертикали. Жалкое зрелище =(

Все это результат стандартного поведения Флексбокс:

  1. Сплющить все дочерние элементы в одну линию и никуда их не переносить. Не самое лучшее решение для галереи, так что изменим его:
.gallery {
 
    flex-wrap: wrap
 
}

Это разрешит перенос элементов на другую строку как и полагается

Изображения перенесены

Изображения перенесены

2. Теперь картинки располагаются в несколько линий. Но они все еще растянуты по вертикали и это определенно не характерно для изображений в галерее.
Свойство align-items флекс-контейнера по умолчанию равно значению stretch

.align-items: stretch

Изменим его:

.gallery {
 
  ...
 
  align-items: flex-start
 
}

Это защитит картинки от растягивания.

Кроме того они выровнены относительно начала вертикальной оси:

Теперь в нашей галерее неискаженные изображения. Почти такие же как и были, пока мы не подключили флексбокс

Теперь в нашей галерее неискаженные изображения. Почти такие же как и были, пока мы не подключили флексбокс

Наша мощная флексбокс-галерея готова.

Преимущества использования Флексбокс

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

Кроме легко получаемой адаптивности, преимущество флексбокс заключается в возможностях выравнивания.
Флекс-контейнер .gallery имеет несколько свойств для настройки выравнивания: flex-direction: row , justify-content: flex-start и align-items: flex-start.
Разметку галереи можно легко поменять поигравшись со следующим значением:

 .gallery {
 
   ...
 
   justify-content:center;
 
}
Теперь изображения идеально отцентрованы по горизонтали

Теперь изображения идеально отцентрованы по горизонтали

Кроме того, картинки могут быть отцентрованы и по горизонтали и по вертикали .gallery.

.gallery {
 
   ...
 
   justify-content:center;
 
   align-items: center;
 
}
А теперь изображения выровнены не только горизонтально, но и вертикально

А теперь изображения выровнены не только горизонтально, но и вертикально

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

Можете посмотреть на действующую Флексбокс галерею здесь.

Пример 2: Как сделать карточки на Флексбокс

Карточки очень популярны в интернете. Гугл, Твиттер, Пинтерест и прочие им подобные – все используют карточки.
В UI-дизайне карточка – это шаблон, объединяющий схожую информацию в адаптивный контейнер. Внешне он напоминает игральную карту.
Существует много хороших способов применения Карточек. Например, сетка с ценами.

Простая сетка цен

Простая сетка цен

Давайте сделаем такую.

Разметка

Каждая карточка построена следующим образом:

<section class="card">
 
  <header>
 
  </header>
 
  <ul>
 
    <li></li>
 
    <li></li>
 
    <li></li>
 
  </ul>
 
  <button></button>
 
</section>

У нас будет как минимум три карточки. Обернем их в div.cards

<div class="cards"></div>

Теперь у нас есть родственные элементы.

В этом примере родственные элементы будут заполнять вcе доступное окно просмотра

.cards {
 
   min-height: 100vh
 
}

Установка Флексбокс

Следующий код инициализирует Флексбокс в контексте блока .card

.cards {
 
  display: flex;
 
  flex-wrap: wrap
 
}

Если вы помните предыдущий пример, flex-wrap позволяет элементам flex-items располагаться в несколько линий, если они не помещаются в контейнер. Давайте зададим .card исходную ширину, используя Флексбокс

.card {
 
  flex: 0 0 250px
 
}

Это свойство устанавливает значения flex-grow и flex-shrink равными 0. Значение flex-basis будет равным 250px.
В том виде, что у нас есть сейчас карточки будут выровнены относительно начала страницы и растянуты по вертикали

Изображения выровнены относительно начала страницы

Изображения выровнены относительно начала страницы

В некоторых случаях это может быть идеальным решением. Но в большинстве случаев – нет.

Поведение флекс-контейнеров по умолчанию

Вид наших карточек является результатом стандартного поведения флекс-контейнеров.
Карточки располагаются в начале страницы (top left) потому что у justify-content установлено значение flex-start.
Кроме того, карточки растянуты на всю высоту родительского элемента, потому что у свойства align-items значение по умолчанию stretch.

Изменение стандартных значений

Мы можем получить впечатляющий результат, изменив стандартные значения флексбокс свойств.
Смотрите сами:

align-items: flex-start; justify-content: center

align-items: flex-start; justify-content: center

align-items: center; justify-content: center

align-items: center; justify-content: center

Мы можете посмотреть код примера на Codepen.

Пример 3: Как сделать сетку на Флексбокс

На концепции, которая обсуждается в этом примере, строятся целые CSS-фреймфорки. Так что это очень важно.

Что такое сетка?

Сетка – это набор прямых пересекающихся вертикальных и горизонтальных линий, использующихся для структурирования контента

Набор пересекающихся прямых (вертикальных, горизонтальных) направляющих линий

Набор пересекающихся прямых (вертикальных, горизонтальных) направляющих линий

Если вам знакомы CSS-фреймворки, такие как Bootstrap, то вы точно использовали сетки раньше.

Давайте начнем с базовой сетки

Базовая сетка

Базовая сетка с равномерно расположенными столбцами

Базовая сетка с равномерно расположенными столбцами

Некоторые свойства этой сетки:

  1. Ячейки клетки располагаются равномерно и растянуты по всей ширине линии.
  2. Все ячейки одинаковой высоты.

Этого очень легко добиться, используя Флейксбокс

<div class="row">
 
  <div class="row_cell">1</div>
 
</div>

Каждая строка .row будет флекс-контейнером.
Каждый элемент внутри .row станет флекс-элементом. Все флех-элементы равномерно распределяются по линии.
С точки зрения дизайна не важно, будет ли у нас три вложенных элемента

<div class="row">
 
  <div class="row_cell">1/3</div>
 
  <div class="row_cell">1/3</div>
 
  <div class="row_cell">1/3</div>
 
</div>

Или 6:

<div class="row">
 
  <div class="row_cell">1/6</div>
 
  <div class="row_cell">1/6</div>
 
  <div class="row_cell">1/6</div>
 
  <div class="row_cell">1/6</div>
 
  <div class="row_cell">1/6</div>
 
  <div class="row_cell">1/6</div>
 
</div>

Или 12:

<div class="row">
 
  <div class="row_cell">1/12</div>
 
  <div class="row_cell">1/12</div>
 
  <div class="row_cell">1/12</div>
 
  <div class="row_cell">1/12</div>
 
  <div class="row_cell">1/12</div>
 
  <div class="row_cell">1/12</div>
 
  <div class="row_cell">1/12</div>
 
  <div class="row_cell">1/12</div>
 
  <div class="row_cell">1/12</div>
 
  <div class="row_cell">1/12</div>
 
  <div class="row_cell">1/12</div>
 
  <div class="row_cell">1/12</div>
 
</div>

Решение

Чтобы получить этот результат необходимы всего два шага.

  1. Инициализировать Флексбокс
    .row {
     
       display: flex;
     
    }
  2. Каждому flex-item позволить заполнять строку в равных пропорциях
    .row_cell {
     
       flex: 1
     
    }

Вот и все.

Объяснение решения

Рубрики: CSSHTML

14 комментариев

Malikero · 02.10.2020 в 20:52

Всем привет! С новым годом, желаю всем счастья, здоровья и удачи в этом году!

Отличный у вас сайт, многие посты очень познавательные.

Joni · 02.10.2020 в 20:53

Здравствуйте. Помогите, пожалуйста, выровнять зеленые блоки по красной линии.http://joxi.ru/gmvzWdDtxWRwdm

    summary · 02.10.2020 в 20:53

    Добрый день. К сожалению, не видя кода я не могу вам помочь. Если вы заведете песочницу на codepen, к примеру, и дадите ссылку, я с удовольствием взгляну и попробую что-нибудь сделать.

Dmitry · 02.10.2020 в 20:53

Невероятная полезная статья. Спасибо, за предостережение о верстке основных компонентов сайта.

    summary · 02.10.2020 в 20:53

    Рада была помочь. Оставайтесь с нами

Stepan · 02.10.2020 в 20:54

В начале статьи идет речь о галерее (в качестве примера). А вот как сделать чтоб выравнивание элементов было по обоим краям , как это происходит при justify-content: space-between;, но при этом последняя (незаполненная) строчка не растягивалась на весь контейнер, а элементы в ней располагались с такимже интервалом как и в заполненной строке, начиная с левого края?

    summary · 02.10.2020 в 20:54

    Здравствуйте. Верно ли я понимаю, что вы хотите, грубо говоря, чтобы первая строка вела себя как при justify-content: space-between, а вторая незаполненная, как при justify-content: flex-start?
    К сожалению, возможностями flex так сделать не получится. Тут нет как таковых “строк”, и поведение определяется для всего набора элементов, независимо, в одной они строке, в двух или пятнадцати.
    Для того, что вы хотите сделать, думаю, вам больше подойдут CSS Grid.

Анатолий · 02.10.2020 в 20:55

Подскажите, по-вашему мнению правильно ли использовать flexbox-разметку, как вот тут paratapok.ru/frontend/5148_css3-flexbox/ (в самом низу страницы), для верстки макетов из psd? Правильно ли так делать?

    summary · 02.10.2020 в 20:55

    Добрый день.
    Вообще, я считаю, что для раскладок лейаутов уже можно и нужно использовать гриды. Это их основное предназначение, у них есть отличные фишки, упрощающие жизнь. Флексы же лучше использовать для стилизации каких-то внутренних блоков.
    С другой стороны, все, что напрямую не запрещено спецификацией – разрешено, поэтому, если вы не знаете гриды, то используйте флексы

Michaeldox · 02.10.2020 в 20:55

Актуально. Подскажите, где я могу найти больше информации по этому вопросу?

    summary · 02.10.2020 в 20:56

    Добрый день. Могу посоветовать курсы htmlacademy (из платных) или посмотреть примеры кода на Scrimba
    Материалов же просто “на почитать” в сети предостаточно.
    Удачи!

Иггорь · 02.10.2020 в 20:56

Хорошо продемонстрировано назначения флексов, а самое главное описано откуда у них ноги растут, а именно из сеток, просто долго разбирался с флэксами без сетки – это вызывало затруднения , а теперь все очень понятно.Спасибо!

Песчаный Воин · 02.10.2020 в 20:56

Добрый день!
Пытаюсь разобраться с тестовым сайтом на поддомене следуя вашей статье и ничего не получается. Какой-то момент упускаю.
https://test.voin-zen.ru/
На основном сайте я все сделал быстро и просто, хочу добиться такого же результат с помощью flexbox.
https://voin-zen.ru/

Мне надо чтобы на мобильном тестовый сайт выглядел как и основной.
Не в 3 элемента в строку, а один элемент на весь экран.
Вот стили, назвал почти как у вас. Не улавливаю момент перехода на мобильник

.news-list-flex-cards {
display: flex;
flex-wrap: wrap;
flex-direction:row;
align-items: flex-start;
justify-content: space-between;
min-height: 100vh;
}

.news-item-flex-card {
flex: 0 0 250px;

}

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

a.news-a {
display:block;
width:299px;
height:189px;
overflow:hidden;

}
a.news-a img {
object-fit: cover;
width: 100%;
height: 189px;
}

    summary · 02.10.2020 в 20:57

    Добрый день!
    У вас в шаблоне есть div c id = “container”, который определяет ширину контентной части страницы. Некий шаблон задает ему width, равный 980px, который все и портит.
    Поведение флексовых потомков напрямую зависит от поведения родителя, но, если родитель не меняется, то и потомкам делать нечего. Замените стиль на max-width, если вам нужно, чтобы область начала уменьшаться.

Комментирование закрыто.