Равная высота элементов внутри элемента сетки с компоновкой CSS grid

у меня есть последовательность статей внутри div длины 4+, без какого-либо тега строки округления. Мне нужно представить его как таблицу из 3 статей (столбцов) в строке, возможно, с display: grid. Каждая статья имеет заголовок, раздел и нижний колонтитул.

как бы я реализовал равную высоту для каждого заголовка, равную высоту для каждого раздела и равный нижний колонтитул высоты, выровненный по нижней части статьи, внутри каждой строки статей? Это вообще возможно? Должен ли я использовать display: table?

PS мне нужно динамически изменять количество статей в строке в зависимости от ширины экрана. Thanx.

HTML-код:

body {
  width: 100%;
  max-width: 1024px;
  margin: auto;
}

.container {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
}

.container article {
  display: grid;
}

article header {
  background-color: #eeeeee;
}

article section {
  background-color: #cccccc;
}

article footer {
  background-color: #dddddd;
}
<div class="container">
  <article>
    <header>
      <h2>Header</h2>
      <h2>Header</h2>
    </header>
    <section>
      <p>Content</p>
    </section>
    <footer>
      <p>Footer</p>
    </footer>
  </article>
  <article>
    <header>
      <h2>Header</h2>
    </header>
    <section>
      <p>Content</p>
      <p>Content</p>
      <p>Content</p>
      <p>Content</p>
      <p>Content</p>
    </section>
    <footer>
      <p>Footer</p>
      <p>Footer</p>
    </footer>
  </article>
  <article>
    <header>
      <h2>Header</h2>
    </header>
    <section>
      <p>Content</p>
      <p>Content</p>
      <p>Content</p>
    </section>
    <footer>
      <p>Footer</p>
    </footer>
  </article>
  <article>
    <header>
      <h2>Header</h2>
    </header>
    <section>
      <p>Content</p>
      <p>Content</p>
      <p>Content</p>
      <p>Content</p>
    </section>
    <footer>
      <p>Footer</p>
      <p>Footer</p>
    </footer>
  </article>
</div>

NB: JS устарел.

https://codepen.io/yudnikov/pen/mBvbGW?editors=1100#0

данное решение:

grid-auto-rows: 1fr; 

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

у меня изначально была эта проблема:

This is what I'am talking about

и grid-auto-rows: 1fr решение приводит к следующему:

Wrong!

2 ответов


это вообще возможно?

tldr; да.

Codepen Demo #1

Codepen Demo # 2 (использует SASS и конфигурируемо)


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

на самом деле есть способ снять это с помощью CSS-сеток и без изменения разметки!

мы могли бы "сгладить" структуру с помощью CSS так, чтобы все компоненты всех статей были частью только одной сетки CSS - контейнера статьи.

это возможно даже без изменения текущей разметки, установив статьи с display: contents

дисплей: содержание (caniuse)

С Caniuse:

display: contents вызывает дочерние элементы элемента, как если бы они были прямыми потомками родителя элемента, игнорируя элемент себя. Это может быть полезно, когда элемент оболочки следует игнорировать при использовании CSS сетки или аналогичных методов компоновки.

Итак, если мы установим статьи с display: contents

.container article {
  display: contents;
}

теперь все заголовки разделов и нижний колонтитул становится (прямым) элементом сетки (контейнера - который имеет display:grid) , которые мы можем организовать с помощью grid-template-areas собственность.

.container {
  display: grid;
  grid-column-gap: 1em; /* horizontal gap between articles */
  grid-template-columns: repeat(3, 1fr);

  grid-template-areas: "header1 header2 header3" 
                       "section1 section2 section3"
                       "footer1 footer2 footer3"
                       "header4 header5 header6" 
                       "section4 section5 section6"
                       "footer4 footer5 footer6"
}

так как каждый заголовок / раздел / нижний колонтитул занимают ровно одну ячейку - это заставляет их занять та же вертикальная высота. Таким образом,например, header1, header2 и header3 будут иметь одинаковую высоту независимо от их содержания.

установка grid-area свойства на каждой из ячеек.

article:nth-child(1) header {
  grid-area: header1;
}
article:nth-child(2) header {
  grid-area: header2;
}
article:nth-child(3) header {
  grid-area: header3;
}
article:nth-child(4) header {
  grid-area: header4;
}
article:nth-child(1) section {
  grid-area: section1;
}
...
article:nth-child(4) section {
  grid-area: section4;
}
article:nth-child(1) footer {
  grid-area: footer1;
}
...
article:nth-child(4) footer {
  grid-area: footer4;
}

наконец, установить вертикальный зазор между каждой строкой статей (начиная со второй строки статей):

article:nth-child(n + 4) header {
  margin-top: 1em;
}

демо:

body {
  width: 100%;
  max-width: 1024px;
  margin: auto;
}

.container {
  display: grid;
  grid-column-gap: 1em;
  grid-template-columns: repeat(3, 1fr);
  grid-template-areas: "header1 header2 header3" 
                      "section1 section2 section3"
                        "footer1 footer2 footer3"
                        "header4 header5 header6" 
                      "section4 section5 section6"
                        "footer4 footer5 footer6"
}

.container article {
  display: contents;
}

article header {
  background-color: #eeeeee;
}

article section {
  background-color: #cccccc;
}

article footer {
  background-color: #dddddd;
}

article:nth-child(n + 4) header {
  margin-top: 1em;
}

article:nth-child(1) header {
  grid-area: header1;
}
article:nth-child(2) header {
  grid-area: header2;
}
article:nth-child(3) header {
  grid-area: header3;
}
article:nth-child(4) header {
  grid-area: header4;
}
article:nth-child(1) section {
  grid-area: section1;
}
article:nth-child(2) section {
  grid-area: section2;
}
article:nth-child(3) section {
  grid-area: section3;
}
article:nth-child(4) section {
  grid-area: section4;
}
article:nth-child(1) footer {
  grid-area: footer1;
}
article:nth-child(2) footer {
  grid-area: footer2;
}
article:nth-child(3) footer {
  grid-area: footer3;
}
article:nth-child(4) footer {
  grid-area: footer4;
}
<div class="container">
    <article>
        <header>
            <h2>Header</h2>
            <h2>Header</h2>
        </header>
        <section>
            <p>Content</p>
        </section>
        <footer>
            <p>Footer</p>
        </footer>
    </article>
    <article>
        <header>
            <h2>Header</h2>
        </header>
        <section>
            <p>Content</p>
            <p>Content</p>
            <p>Content</p>
            <p>Content</p>
            <p>Content</p>
        </section>
        <footer>
            <p>Footer</p>
            <p>Footer</p>
        </footer>
    </article>
    <article>
        <header>
            <h2>Header</h2>
        </header>
        <section>
            <p>Content</p>
            <p>Content</p>
            <p>Content</p>
        </section>
        <footer>
            <p>Footer</p>
        </footer>
    </article>
    <article>
        <header>
            <h2>Header</h2>
        </header>
        <section>
            <p>Content</p>
            <p>Content</p>
            <p>Content</p>
            <p>Content</p>
        </section>
        <footer>
            <p>Footer</p>
            <p>Footer</p>
        </footer>
    </article>
</div>

Codepen Demo)

конечно, вместо использования grid-template-areas + grid-area свойства мы могли бы вместо этого использовать grid-row + grid-column свойства для достижения того же результата - сайт CodePen демо


Примечание: I поймите, что вышеизложенное многословно и не совсем оптимальное решение - но моя точка зрения здесь в том, что возможно. Кроме того,мы могли бы использовать петли SASS, чтобы сделать этот код намного чище, а также настраиваемый.

было бы неплохо, если бы был какой-нибудь способ повторить шаблон используя grid-template-areas - что-то вроде:

псевдо-код (не юридическим):

grid-template-areas: repeat("header1 header2 header3" 
                           "section1 section2 section3"
                           "footer1 footer2 footer3")

...тогда мы могли бы получить более динамичное решение, которое бы работа для n статьи решение, установив сетку-область с помощью nth-ребенка, как:

article:nth-child(3n + 1) header {
  grid-area: header1;
} 

etc. ... но я не думаю, что это возможно на данный момент (или, может быть, это не нужно, потому что подсеток сможет ли это сделать?)


NB:

модуль компоновки сетки Уровень 2 вводит Подсеток что сделает эту проблему более легкой разрешить и без использовать display: contents


должен ли я использовать display: table?

для макета, который вам нужен - display:table не поможет. Во-первых, вам придется полностью реструктурировать свою разметку в group статья вместе как приложение к статьям, вам нужно будет взломать, чтобы стиль таблицы выглядел как "статьи", но даже тогда - таблицы не оборачиваются, поэтому вам нужно будет обернуть каждые три статьи в отдельную таблицу.... даже если бы это было возможно это было бы очень грязно и трудно поддерживать.


самая простая идея, которая приходит мне на ум-это использовать процент. Например:

.container{
    width: 30%;
    height: 80%;
}

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

https://www.w3schools.com/cssref/css_default_values.asp

для разных устройств просто используйте отдельные CSS-файлы...