Выровняйте элементы с разной высотой в сетке, чтобы они соответствовали линиям выравнивания


Я хочу создать страницу, на которой мои элементы будут отображаться в сетке. Я хочу выровнять элементы по строкам. я хочу визуально достичь следующего результата , но не знаю как: https://codepen.io/shirkit/pen/KvZKOE/

И в настоящее время у меня есть это:

var back = ["red","blue","gray","black","green","cyan","brown","magenta"];
var i = 0;

$('#container .card').children().each(function() {
 $(this).css('background-color',back[i++]);
 if (i == back.length) i = 0;
});
#container {
 display: flex;
 flex-direction: row;
}

.card {
 max-width: 200px;
  width: 100%;
}

.card .image {
 height: 150px;
}

.card .text {
 height: 100px;
}

.card .list {
 height: 50px;
}

#z1 .image {
  height: 175px;
}

#z2 .text {
  height: 120px;
}

#z3 .list {
  height: 60px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="container">
 <div id="z1" class="card">
  <div class="image"></div>
  <div class="text"></div>
  <div class="list"></div>
 </div>
 <div id="z2" class="card">
  <div class="image"></div>
  <div class="text"></div>
  <div class="list"></div>
 </div>
 <div id="z3" class="card">
  <div class="image"></div>
  <div class="text"></div>
  <div class="list"></div>
 </div>
</div>

Уточнение: высоты на селекторах идентификаторов #z1 .image, #z2.text #z3 .list существуют только для моделирования высоты, которую будут иметь компоненты. Следовательно, это Нет возможности изменить эти значения. Также обратите внимание, что значения высоты этих элементов/контейнеров не известны заранее, поэтому установка полей также не является опцией.

Текущий код показан не так, как он есть в данный момент, он просто показывает, как визуально выглядит в данный момент, но он должен следовать этой структуре, a container для всего, a card для элемента и элементов внутри карты.

Теперь я знаю, как это сделать, если я не помещаю элементы в элемент .card, а затем использую CSS display: grid в #container. У меня были бы элементы .image/.text/.list как прямые дети от #container, но это последнее средство, я хотел альтернативу.

В настоящее время я ищу решение, которое позволит мне сохранить элементы .card и иметь возможные резервные варианты.

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

4 6

4 ответа:

С вашей текущей структурой HTML, я не знаком с любыми чистыми способами CSS для достижения вашего конечного результата. Ключевая проблема заключается в том, что отдельные элементы в каждой соседней колонке никак не соотносятся со своим окружением. Если бы ваши ячейки были горизонтальными, мы могли бы использовать CSS, например table-row - потому что "ячейки являются потомками строк, а не столбцов."(W3 )

С учетом сказанного, вы не упомянули, что ищете чистое решение CSS, и как вы уже есть используя jQuery, я подумал, что это было бы прекрасным решением для сохранения структуры HTML при достижении желаемого макета.

В приведенном ниже коде я перебираю каждый набор компонентов (изображение, текст, список), чтобы определить, какая карта имеет самую высокую для каждой, а затем размечаю другие карты, используя margin-bottom на каждом из этих более коротких компонентов, чтобы сделать их равными.

var back = ["red", "blue", "gray", "black", "green", "cyan", "brown", "magenta"];
var i = 0;

$('#container .card').children().each(function() {
  $(this).css('background-color', back[i++]);
  if (i == back.length) i = 0;
});

var components = ['image', 'text', 'list'];
$.each(components, function(i, j) {
  var $elements = $('.card .' + j);
  var heights = [];
  var tallest = 0;

  $elements.each(function(i) {
    var height = $(this).height();
    heights[i] = height;
    if (height > tallest) {
      tallest = height;
    }
  });

  $.each(heights, function(i, j) {
    var diff = tallest - j;
    if (diff) {
      $elements.eq(i).css('margin-bottom', diff);
    }
  });
});
#container {
  display: flex;
}

.card {
  max-width: 200px;
  width: 100%;
}

.card .image {
  height: 150px;
}

.card .text {
  height: 100px;
}

.card .list {
  height: 50px;
}

#z1 .image {
  height: 175px;
}

#z2 .text {
  height: 120px;
}

#z3 .list {
  height: 60px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="container">
  <div id="z1" class="card">
    <div class="image"></div>
    <div class="text"></div>
    <div class="list"></div>
  </div>
  <div id="z2" class="card">
    <div class="image"></div>
    <div class="text"></div>
    <div class="list"></div>
  </div>
  <div id="z3" class="card">
    <div class="image"></div>
    <div class="text"></div>
    <div class="list"></div>
  </div>
</div>
#container {
 display: flex;
 flex-direction: row;
}

.card {
 max-width: 200px;
  width: 100%;
}

#z2  .image {
 height: 150px;
 max-height: 175px;
 margin-bottom:25px;
}
#z3  .image {
 height: 150px;
 max-height: 175px;
 margin-bottom:25px;
}
#z1 .text {
 height: 100px;
 margin-bottom:20px;
}
#z3 .text {
 height: 100px;
 margin-bottom:20px;
}
.card .list {
 height: 50px;
}

#z1 .image {
  height: 175px;
}
#z2 .image{

}

#z2 .text {
  height: 120px;
}

#z3 .list {
  height: 60px;
}

Это css для вашего желаемого вывода. но вы должны использовать jquery его рекомендуется Вы хотели чистый css это он.

Вместо кода ниже

<style type="text/css">
#z1 .image {
  height: 175px; 
}
#z2 .text {
  height: 120px;
}
#z3 .list {
  height: 60px;
}
</style>

Используйте этот код

<style type="text/css">
#z1 .image {
  height: auto; 
}
#z2 .text {
  height: auto;
}
#z3 .list {
  height: auto;
}
</style>

Используйте для этого схему кладки, например https://masonry.desandro.com/. это поможет достичь компоновки ниже с небольшим количеством JS. Использование чистого CSS может не дать полностью кроссбраузерного решения, особенно если вы попытаетесь использовать flexbox

Образец планировки кладки