【问题标题】:Flex-wrap with rows of different heights具有不同高度行的 Flex-wrap
【发布时间】:2016-09-29 22:42:46
【问题描述】:

我正在实现带有哈希标签链接的纯 CSS 选项卡。我非常接近,但不能完全让柔性包装正常工作。为了让所有东西都能按照我想要的方式工作,:target(我之前已经用单选按钮做到了这一点,这提供了更多的灵活性),我需要同一级别的所有选项卡和所有部分,所以我有:

body
  section
  anchor
  section
  anchor
  ...

然后我可以使用 flexbox ordering 使所有锚点首先出现并适当地设置样式,将所有部分设置为 100% 宽度并使用 flex-wrap 允许它们换行到下一行。问题是我似乎无法控制第一行的高度。这是怎么回事?

body {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  margin: 0;
  padding: 0;
  height: 100vh;
  outline: 1px solid green;
}
body > a {
  padding: 10px;
  margin: 0 5px;
  order: -1;
  flex-grow: 0;
  border: solid gray;
  border-width: 1px 1px 0 1px;
}
body > a:last-of-type {
  order: -2;
}
section {
  flex-grow: 1;
  width: 100%;
  background-color: cornsilk;
  display: none;
  border-top: 1px solid grey;
}
section:last-of-type {
  display: flex;
}
a {
  font-weight: normal;
}
a:last-of-type {
  font-weight: bold;
}
:target {
  display: flex;
}
:target ~ section {
  display: none;
}
:target ~ a {
  font-weight: normal;
}
:target + a {
  font-weight: bold;
}
<section id="advanced">
	Advanced Stuff
</section>
<a href="#advanced">Advanced</a>

<section id="home">
	Home Things
</section>
<a href="#home">Home</a>

Slightly easier to play with jsbin

问题在于第一行中的选项卡拉伸到可见部分的高度,而不是折叠到其内容的高度。即使是特定的heightmax-height 似乎也被忽略了。

请注意,这个问题专门针对使用 flexbox 包装时的行高。我知道在 css 和 js 中构建选项卡的一百万种不同方法。我特意寻找对flex-wrap的更深入了解。

【问题讨论】:

  • 那么,当标签换行时,您究竟希望发生什么?也许你可以说明你想要的结果。
  • @Michael_B 运行示例 - 您看到它们如何拉伸到与部分相同的高度,而不是折叠到其内容的大小?我希望它们看起来像标签,但它们都被拉长了。我希望两行都根据内容调整大小
  • 弹性容器的两个初始设置是align-items: stretchalign-content: stretch。您可以通过将值更改为 flex-start 来覆盖它。
  • @Michael_B align-content 似乎让我非常接近,但由于某种原因,这使得 section 不再垂直填充。
  • 所以您希望stretch 用于宽屏,flex-start 用于窄屏?

标签: html css flexbox


【解决方案1】:

如果使用calc 计算该部分的高度已知选项卡的高度,我只会看到一个解决方案:

body {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  align-items: flex-start;
  align-content: flex-start;
  margin: 0;
  padding: 0;
  height: 100vh;
}

body > a {
  padding: 0 10px;
  margin: 0 5px;
  order: -1;
  flex: 0 1 auto;
  border: solid gray;
  border-width: 1px 1px 0 1px;
  line-height: 30px;
}

body > a:last-of-type {
  order: -2;
}

section {
  flex: 0 1 100%;
  background-color: cornsilk;
  display: none;
  border-top: 1px solid grey;
  height: calc(100% - 32px)
}

section:last-of-type {
  display: block;
}

a {
  font-weight: normal;
}

a:last-of-type {
  font-weight: bold;
}

:target {
  display: block;
}

:target ~ section {
  display: none;
}

:target ~ a {
  font-weight: normal;
}

:target + a {
  font-weight: bold;
}
<section id="advanced">
  Advanced Stuff
</section>
<a href="#advanced">Advanced</a>

<section id="home">
  Home Things
</section>
<a href="#home">Home</a>

【讨论】:

  • 如果你这样做,你不需要calc。删除align-content 规则并将所有body&gt;a 设置为具有height: 32px。实际上不是一个糟糕的解决方案......
【解决方案2】:

body 中删除height: 100vh 和从section 中删除flex-grow: 1;

发生的情况是您将正文设置为全高,然后告诉该部分增加全部可用空间,因此它们填充浏览器高度。

body {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  margin: 0;
  padding: 0;
  outline: 1px solid green;
}
body > a {
  padding: 10px;
  margin: 0 5px;
  order: -1;
  flex-grow: 0;
  border: solid gray;
  border-width: 1px 1px 0 1px;
}
body > a:last-of-type {
  order: -2;
}
section {
  width: 100%;
  background-color: cornsilk;
  display: none;
  border-top: 1px solid grey;
}
section:last-of-type {
  display: flex;
}
a {
  font-weight: normal;
}
a:last-of-type {
  font-weight: bold;
}
:target {
  display: flex;
}
:target ~ section {
  display: none;
}
:target ~ a {
  font-weight: normal;
}
:target + a {
  font-weight: bold;
}
<section id="advanced">
	Advanced Stuff
</section>
<a href="#advanced">Advanced</a>

<section id="home">
	Home Things
</section>
<a href="#home">Home</a>

示例 2,使用包装器

body {
  display: flex;
  flex-direction: column;
  margin: 0;
  padding: 0;
  outline: 1px solid green;
  height: 100vh;
}
body > div {
  flex: 0;
  order: 1;
}
section {
  flex: 1;
  background-color: cornsilk;
  display: none;
  border-top: 1px solid grey;
  order: 2;
}
body > div > a {
  display: inline-block;
  padding: 10px;
  margin: 0 5px;
  border: solid gray;
  border-width: 1px 1px 0 1px;
}
section:last-of-type {
  display: flex;
}
a {
  font-weight: normal;
}
a:first-of-type {
  font-weight: bold;
}
:target {
  display: flex;
}
:target ~ section {
  display: none;
}
:target ~ div a {
  font-weight: normal;
}
#home:target ~ div a[href='#home'],
#advanced:target ~ div a[href='#advanced'] {
  font-weight: bold;
}
<section id="advanced">
	Advanced Stuff
</section>

<section id="home">
	Home Things
</section>

<div>
  <a href="#home">Home</a>
  <a href="#advanced">Advanced</a>
</div>

【讨论】:

  • 嗯...是的,但是删除 height: 100vh 从根本上改变了它的作用。该部分将不再扩展到底部。实际上,这可能是min-height btw。
  • @GeorgeMauer 好的,所以当您说我希望两行都根据内容调整大小时,这实际上是什么意思? ... section 应始终填充 tabs 留下的剩余空间?
  • 完全正确。该部分应该垂直填充空间(它有flex-grow: 1)并且选项卡应该折叠到它们的内容
  • @GeorgeMauer 使用包装器更新了 2:nd 建议,因为现有标记/css 无法实现所需的行为
  • 我很欣赏这一点,它有很大帮助。将接受迈克尔的回答,因为它有助于更​​好地向我解释发生了什么,并教会了我一些关于 flex-wrap 的知识,但非常感谢!
【解决方案3】:

弹性容器的两个初始设置是align-items: stretchalign-content: stretch。您可以通过将值更改为 flex-start 来覆盖它。

但这似乎只能解决部分问题。您还希望选定的包装项目拉伸容器的整个高度。

这不会发生,因为 当 flex 项目包装时,它们只占用包含其内容所需的最小尺寸。

来自 flexbox 规范:

6. Flex Lines

在多行 flex 容器中(即使只有一行), 每行的交叉大小是包含 行上的弹性项目(由于align-self而对齐后),以及 行在 flex 容器中与 align-content 对齐 属性。

换句话说,当基于行的弹性容器中有多行时,每行的垂直高度(“交叉大小”)是“需要的最小大小包含行上的弹性项目”

要使您的布局正常工作,您需要结合使用行方向和列方向的弹性容器,以及对 HTML 的调整。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-12-05
    • 2016-08-03
    • 2019-04-13
    • 2020-07-25
    • 2017-08-30
    • 2019-11-21
    • 1970-01-01
    相关资源
    最近更新 更多