CSS网格布局

时间:2017-10-18 18:19:00

标签: css grid height rows css-grid

我在4+长度的div中有一系列文章,没有任何舍入行标记。我需要将其表示为每行3篇文章(列)的表格,可能包含display: grid。每篇文章都有标题,部分和页脚。

我如何为每个标题实现相同的高度,每个部分的高度相等,以及与文章底部对齐的相等高度的页脚,在每行文章中?它甚至可能吗?我应该使用display: table吗?

PS我需要动态更改每行的文章数量,具体取决于屏幕宽度。感谢名单。

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>

注意:JS已被弃用。

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

This solution

grid-auto-rows: 1fr; 

已被提议为重复,但事实并非如此。它只会使物品的高度相等,例如每篇文章的标题大小不同。

我原本遇到这个问题:

This is what I'am talking about

grid-auto-rows: 1fr解决方案产生了这个:

Wrong!

2 个答案:

答案 0 :(得分:10)

  

甚至可能吗?

tldr;是

Codepen Demo #1

Codepen Demo # 2(使用SASS并且可配置)

<小时/> 这里的困难在于每篇文章本身都是一个网格,因此任何一篇文章都不了解另一篇文章。因此,一个文章的组件(如标题)无法根据另一篇文章中标题的高度进行调整。

实际上有一种方法可以通过css网格来实现这一目标。没有改变任何标记!

我们可以“压扁”&#39;使用CSS的结构使得所有文章的所有组件都只是一个CSS网格的一部分 - 文章容器。

通过使用display: contents

设置文章,甚至无需更改当前标记

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;
}

演示:

&#13;
&#13;
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;
}
&#13;
<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>
&#13;
&#13;
&#13;

Codepen Demo)

当然,我们可以使用grid-template-areas + grid-area属性来代替使用grid-row + grid-column属性来获得相同的结果 - {{ 3}}

注意:我确实认识到上述内容详细而且不是最佳解决方案 - 但我的观点是可能。另外,Codepen demo

如果使用grid-template-areas 重复模式有某种方法可能会很好 - 例如:

伪代码(不合法):

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

...然后我们可以通过使用nth-child设置网格区域来获得更适合n文章解决方案的动态解决方案:

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

等。 ......但我现在认为不可能(或者可能没有必要,因为we could use SASS loops to make that code much cleaner and also configurable能够做到这一点吗?)

NB:

网格布局模块第2级引入subgrids,这将使这个问题更容易解决,而不必使用display: contents

  

我应该使用display:table吗?

对于您需要的布局 - display:table不会有多大帮助。首先,您必须完全重新构建您的标记,以便将文章组件组合在一起,与文章相关联,您必须在桌面上进行样式设置,使其看起来像&#39;文章&#39;但即便如此 - 桌子也没有包裹,所以你需要将每三篇文章包装成一张单独的表格......即使有可能它也会非常混乱,难以维护。

答案 1 :(得分:-2)

我想到的最简单的想法是使用procntage。例如:

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

要完全控制布局,请查看CSS默认值参考:

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

对于不同的设备,只需使用单独的CSS文件......