【问题标题】:Make ALL flex-items wrap (like flex-direction: column) when any one flex-item too wide for flex-container当任何一个弹性项目对于弹性容器来说太宽时,使所有弹性项目都换行(如弹性方向:列)
【发布时间】:2020-06-16 12:05:05
【问题描述】:

这个用例是一个带有单选按钮的响应式表单。当在 PC 大屏幕上时,所有单选按钮通常会在屏幕上排成一行(例如带有 flex-direction: row 的非包装 flex 容器中的 flex 项)。在电话上,并非所有单选按钮通常都适合一条线。如果任何一个单选按钮不适合,我希望它们都每行显示一个(例如带有flex-direction: column 的弹性容器中的弹性项目)。

如果我知道我的单选按钮标签将有多长,这将很容易,但我不知道(它们来自客户端可配置数据库)。

所以我想要的是这样的:

<html>
  <head>
    <title>Responsive Radio Button</title>
    <style type="text/css">
      @media (min-width: 652px) {
        .flexContainer {
          display:flex;
          flex-direction: row;
        }
      }
      @media (max-width: 652px) {
        .flexContainer {
          display:flex;
          flex-direction: column;
        }
      }
      </style>
  </head>
  <body>
    <div class='flexContainer'>
      <div>Medium Length div</div>
      <div>Short div</div>
      <div>Longest div in this entire html page!</div>
      </div>
    </div>
  </body>
</html>

我事先不知道@media (min-width: /max-width:) 断点是什么。

我尝试了什么

这是我正在进行的代码

<html>
  <head>
    <title>Responsive Radio Button</title>
    <style type="text/css">
      .flexContainer {
        display: flex;
        flex-wrap: wrap;
        justify-content:stretch;
        /** border so I can see what is going on */
        border: 1px dotted lightblue;
      }
      .flexItem {
        /** white-space and min-width stop text wrapping */
        white-space: nowrap; 
        min-width: max-content;
        /** next three lines could be shortened to flex: 1 0 0px; (grow shrink basis) */
        flex-basis: 0;
        flex-grow: 1;
        flex-shrink: 0;
        /** border and margin so I can see what is going on */
        border: 1px solid black;
        margin: 2px;
      }
      </style>
  </head>
  <body>
    <div class='flexContainer'>
      <div class='flexItem'>Medium Length div</div>
      <div class='flexItem'>Short div</div>
      <div class='flexItem'>Short div</div>
      <div class='flexItem'>Short div</div>
      <div class='flexItem'>Longest div in this entire html page!</div>
      </div>
    </div>
  </body>
</html>

弹性:1 0 0 这用于使所有弹性项目的主轴大小相等。但是当包裹开始时,主轴尺寸的相等性下降。如果弹性项目都保持相同的大小,那么它们对于父弹性容器来说都太长了,所以都会换行。 但是,这不会发生,因为每个弹性项目的最小尺寸是不同的,所以虽然弹性项目永远不会缩小,但它们都会开始增长以从不同的尺寸开始填充剩余的空间。

就像我想要一个flex-basis: largest-sibling,我的意思是最小的弹性项目开始时的大小与最大的弹性项目相同,并且永远不会小于最大的弹性项目。

【问题讨论】:

  • 无法使用 flexbox 或任何其他布局方法。需要Javascript

标签: html css flexbox


【解决方案1】:

这里的主要见解是:

1) This problem is a two dimensional problem.

二维问题:用display: grid;解决

一维问题:用display: flex;解决

我认为这个问题是一个单维问题,因为我希望我的单选按钮在一种情况下是水平的,而在另一种情况下是垂直的——两者都指的是一个单一的维度。我错了,因为它涉及垂直和水平之间的过渡,所以这是一个二维问题。

2)grid-auto-flow: column;

我还必须选择一个任意的视口宽度来从垂直到水平滑动,并使用@media 语句。

这个答案并不完美,它没有同样尺寸的尺寸,当它们不在一个星期性线时,但它会实现我想要的东西:

<html>
  <head>
    <title>Responsive Radio Button</title>
    <style type="text/css">
      @media(max-width: 600px) {
        .resize {
          grid-template-columns: 600px;
        }
      }
      @media(min-width: 600px) {
        .resize {
          grid-auto-flow: column;
          grid-auto-columns: 1fr;
        }
      }
      .gridContainer {
        display: grid;

        /** border so I can see what is going on */
        border: 1px dotted lightblue;
      }
      .gridItem {
        /** white-space and min-width stop text wrapping **/
        white-space: nowrap; 
        min-width: max-content;
        /** border and margin so I can see what is going on */
        border: 1px solid black;
        margin: 2px;

      }
      </style>
  </head>
  <body>
    <div class='gridContainer resize'>
      <div class='gridItem'>Medium Length div</div>
      <div class='gridItem'>Short div</div>
      <div class='gridItem'>Short div</div>
      <div class='gridItem'>Short div</div>
      <div class='gridItem'>Longest div in this entire html page!</div>
      </div>
    </div>
  </body>
</html>

【讨论】:

  • 如果您愿意使用 @media,那么我认为 flex 更适合您,因为您只需更改 flex-direction 就可以了。 gap-rowgap-column 现在得到了相当广泛的支持,我认为这是对 flex 而不是网格的一种很好的使用。不过和你一样,我真的希望避免媒体查询,并希望有一种方式告诉 Flex“如果你能把它全部放在一行中,那么就做flex-direction: row,否则就做flex-direction: column
【解决方案2】:

我认为CSS网格可以实现最接近你需求的答案

.flexContainer {
  display: grid;
  grid-template-columns: repeat(auto-fit,minmax(600px,1fr))
}
<div class='flexContainer'>
      <div>Medium Length div</div>
      <div>Short div</div>
      <div>Longest div in this entire html page!</div>
  </div>

Auto sizing columns in CSS grid

您可以在此处阅读有关它的更多信息并对其进行调整以适应您的需求

【讨论】:

  • 谢谢 m_sultan - 你让我重新阅读了关于 grid vs flex 的 doco,正如developer.mozilla.org/en-US/docs/Web/CSS/CSS_Grid_Layout/… 所说,grid 是二维的,flex 是一维的。即使我只有一行或一列,我的问题是二维的。我现在正在尝试您的建议,但它不会将它们全部放在同一行 - 它们溢出到第二行但保持一致的大小(这是一个改进) - 将继续尝试
【解决方案3】:

这是我从你的编码中得到的。看看对你有没有帮助

<html>
  <head>
    <title>Responsive Radio Button</title>
    <style type="text/css">
      .flexContainer {
        display: flex;
        flex-wrap: wrap;
        justify-content:stretch;
        /** border so I can see what is going on */
        border: 1px dotted lightblue;
      }
      .flexItem {
        /** white-space and min-width stop text wrapping */
        white-space: nowrap; 
        min-width: max-content;
        /** next three lines could be shortened to flex: 1 0 0px; (grow shrink basis) */
        flex-basis: 0;
        flex-grow: 1;
        flex-shrink: 0;
        /** border and margin so I can see what is going on */
        border: 1px solid black;
        margin: 2px;
      }
      @media only screen and (max-width: 600px) {
        .flexContainer {
          flex-flow: column;
        }
      }

      </style>
  </head>
  <body>
    <div class='flexContainer'>
      <div class='flexItem'>Medium Length div</div>
      <div class='flexItem'>Short div</div>
      <div class='flexItem'>Short div</div>
      <div class='flexItem'>Short div</div>
      <div class='flexItem'>Longest div in this entire html page!</div>
      </div>
    </div>
  </body>
</html>

【讨论】:

    猜你喜欢
    • 2018-06-26
    • 2014-08-09
    • 2016-10-22
    • 1970-01-01
    • 2021-11-01
    • 1970-01-01
    • 2017-10-22
    相关资源
    最近更新 更多