Выравнивание элементов flex с разной высотой в одном контейнере

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

просмотрите этот JSFiddle для примера flexbox.

просмотрите этот пример jsfiddle a float

макет сетки

<div class="flex-container">
 <div class="large-flex-item">
</div>
<div class="small-flex-item">
 </div>
<div class="small-flex-item">
 </div>
</div>

в CSS

 .flex-container {
   display: flex;
   flex-direction: row;
   flex-wrap: wrap;
   align-items: flex-start;
   max-width: 500px;
   margin-right: auto;
   margin-left: auto;
 }

 .small-flex-item {
   flex-basis: 33.333%;
   background: #000;
   padding-top: 30%;
 }

 .large-flex-item {
   flex-basis: 66.667%;
   background: #333;
   padding-top: 60%;
 }

2 ответов


Вы можете достичь макета раскроя контейнеры Flex.

HTML-код

<div class="flex-container">

  <div class="large-flex-item"></div><!-- flex item #1 -->

  <div class="flex-container-inner"><!-- flex item #2 & nested flex container -->
     <div class="small-flex-item"></div><!-- this flex item and sibling will align... -->
     <div class="small-flex-item"></div><!-- ... in column next to .large-flex-item -->
  </div>

</div>

в CSS

 .flex-container {
   display: flex;
   width: 500px;
   margin-right: auto;
   margin-left: auto;
 }

 .large-flex-item {
   flex-basis: 66.667%;
   height: 200px;
   background: #333;
 }

.flex-container-inner {
  display: flex;
  flex-direction: column;
  flex-grow: 1;
}

.small-flex-item {
   flex-basis: 100%;
   height: 100px;
   background: #000;
 }

демо


Flexbox не любит элементы flex, которые расширяются через несколько столбцов или строк, потому что на самом деле flexbox не имеет понятия сетки.

однако, используя некоторые трюки, вы можете достичь этого макета (и более сложные тоже):

  • используйте макет строки

    ┌─┬─┬─┐
    │1│2│3│
    └─┴─┴─┘
    
  • разрешить разрывы строк с flex-wrap: wrap.

  • используйте псевдоэлемент для принудительного разрыва строки после 2

    ┌─┬─┐
    │1│2│
    ├─┼─┘
    │3│
    └─┘
    
  • использовать width: 33% 2 и 3, и flex: 1 на 1.

    ┌───────────────┬─────┐
    │1              │2    │
    ├─────┬─────────┴─────┘
    │3    │
    └─────┘
    
  • Set margin-left: auto на 3

    ┌───────────────┬─────┐
    │1              │2    │
    └───────────────┼─────┤
                    │3    │
                    └─────┘
    
  • выберите некоторую длину x

  • Set height: x 2 и 3. Set height: 2*x для 1.

    ┌───────────────┬─────┐
    │1              │2    │
    │               ├─────┘
    │               │
    └───────────────┼─────┐
                    │3    │
                    └─────┘
    
  • Set margin-bottom: -x до 1:

    ┌───────────────┬─────┐
    │1              │2    │
    │               ├─────┤
    │               │3    │
    └───────────────┴─────┘
    
  • Примечание flexbox вводит auto как новое начальное значение min-width. Это может позволить содержимому заставить некоторые коробки расти. Это нарушит макет, поэтому отключите его с помощью min-width: 0 или параметр overflow ни к чему, кроме visible.

вот код:

.flex-container {
  display: flex;
  flex-flow: row wrap;
}
.flex-item {
  overflow: hidden;
}
.flex-container::after {
  content: '';
  width: 100%; /* Force line break */
}
.large.flex-item {
  flex: 1;
  height: 200px;
  margin-bottom: -100px;
  background: red;
}
.small.flex-item {
  width: 33.333%;
  height: 100px;
  background: green;
}
.small.flex-item + .small.flex-item {
  order: 1;
  margin-left: auto;
  background: blue;
}
<div class="flex-container">
  <div class="large flex-item">1</div>
  <div class="small flex-item">2</div>
  <div class="small flex-item">3</div>
</div>

однако было бы проще изменить HTML, чтобы иметь вложенные flexboxes.