【问题标题】:CSS Flexbox: How to go from single-column to two-column layout with alternating elements?CSS Flexbox:如何从单列布局到具有交替元素的两列布局?
【发布时间】:2021-05-19 07:18:51
【问题描述】:

我想在更宽的屏幕上以两列显示带有标签和表单元素的表单,并在较小的屏幕上显示带有交替标签/输入的单列。

所以我需要离开

label
input
label
input

在小屏幕上

label | label
input | input

在较大的。我想使用 flexbox,因为我需要支持 IE11,而且我认为尽管它有怪癖,但支持它比实现新旧网格语法更容易。

我可以使用:nth-of-type()(见下文)来实现这一点,如果没有任何其他解决方案,我会这样做,但我需要知道表单中将出现的元素数量和以后表单元素的数量发生变化时,我必须扩展 CSS。

我还可以将每个标签/表单元素对包装在一个容器中并将它们并排放置,但我还想考虑具有不同高度的标签和输入(参见带有标签 3 + 4 的行),其中行不通(它需要像 subgrid 这样的东西来实现这一点)。

.container {
  display: flex;
  flex-wrap: wrap;
}

.container>* {
  width: 50%;
  box-sizing: border-box;
}

.container label {
  margin-top: 0.3em;
  align-self: flex-end;
}

.container input {
  margin-top: 0.3em;
  align-self: flex-start;
}

@media screen and (min-width: 400px) {
  .container label:nth-of-type(1),
  .container label:nth-of-type(2) {
    order: 1;
  }
  .container input:nth-of-type(1),
  .container input:nth-of-type(2) {
    order: 2;
  }
  .container label:nth-of-type(3),
  .container label:nth-of-type(4) {
    order: 3;
  }
  .container input:nth-of-type(3),
  .container input:nth-of-type(4) {
    order: 4;
  }
  .container label:nth-of-type(5),
  .container label:nth-of-type(6) {
    order: 5;
  }
  .container input:nth-of-type(5),
  .container input:nth-of-type(6) {
    order: 6;
  }
}
<div class="container">
  <label>label1</label>
  <input placeholder="input1">
  <label>label2</label>
  <input placeholder="input2">
  <label>label3</label>
  <input placeholder="input3">
  <label>label4<br>lorem ipsum</label>
  <input placeholder="input4">
  <label>label5</label>
  <input placeholder="input5" style="height: 3em">
  <label>label6</label>
  <input placeholder="input6">
</div>

有没有更优雅/更动态的方式来做到这一点?

【问题讨论】:

    标签: css forms flexbox


    【解决方案1】:

    你可以这样做。

    .container {
      display: flex;
      flex-wrap: wrap;
    }
    
    .field {
      display: flex;
      flex-direction: column;
      flex: 1 1 50%;
      justify-content: flex-end;
    }
    
    .field:last-child {
      align-self: flex-start;
    }
    
    
    @media (max-width: 400px) {
        .field {
            flex: 1 1 100%;
        }
    }
    <div class="container">
      <div class="field">
        <label>label1</label>
        <input placeholder="input1">
      </div>
      <div class="field">
        <label>label2</label>
        <input placeholder="input2">
      </div>
      <div class="field">
        <label>label3</label>
        <input placeholder="input3">
      </div>
      <div class="field">
        <label>label4<br>lorem ipsum</label>
        <input placeholder="input4">
      </div>
      <div class="field">
        <label>label5</label>
        <input placeholder="input5" style="height: 3em">
      </div>
      <div class="field">
        <label>label6</label>
        <input placeholder="input6">
      </div>
    </div>

    【讨论】:

    • 不幸的是,这不适用于不同的标签高度(参见标签 3 / 4)
    • 现在它被标签 5 + 6 打破;)
    • 现在呢?还是您想要它在您的代码中的确切显示方式?
    • 标签应始终垂直对齐底部,表单元素顶部,如我的示例所示
    • 您可以明确处理某些情况。查看更新
    【解决方案2】:

    CSS 网格可以轻松做到这一点:

    .container {
      display: grid;
      grid-template-columns:1fr 1fr;
      grid-auto-flow:dense;
      align-items:start;
    }
    
    @media (min-width:400px) {
     input:nth-of-type(2n + 1) {
       grid-column:1; /* for each two input move the first to the first column, that's it !*/
     }
    }
    
    .container>* {
      box-sizing: border-box;
    }
    
    .container label {
      margin-top: 0.3em;
      align-self: flex-end;
    }
    
    .container input {
      margin-top: 0.3em;
    }
    <div class="container">
      <label>label1</label>
      <input placeholder="input1">
      <label>label2</label>
      <input placeholder="input2">
      <label>label3</label>
      <input placeholder="input3">
      <label>label4<br>lorem ipsum</label>
      <input placeholder="input4">
      <label>label5</label>
      <input placeholder="input5" style="height: 3em">
      <label>label6</label>
      <input placeholder="input6">
    </div>

    【讨论】:

    • 不错!你一定会喜欢 CSS Grid!如果我能为这个项目放弃 IE11...
    【解决方案3】:

    除了order 和媒体查询,如果你想坚持flex 模型,你的代码没有太多选择。

    您可以尝试:nth-child(n) ~ element 来减少要编写的 CSS。

    这是一个例子,但与你的非常相似,甚至可能不是答案:)

    div {
      display: flex;
      flex-wrap: wrap;
      gap: 0 10px;/* need a gap in between the cols ? */
    }
    div > * {
      min-width: 350px;
      width: 40%;
      flex-grow: 1;
      box-sizing: border-box;
    }
    @media screen and (min-width: 710px) {/* equals twice the min-width + the gap */
      input {
        margin-bottom: auto;/* */
      }
      label {
        order: -1;
        margin-top: auto;/* */
        padding-top: 0.5em;/* margin already used */
      }
      :nth-child(3) ~ label {
        order: 0;
      }
      :nth-child(4) ~ input {
        order: 1;
      }
      :nth-child(7) ~ label {
        order: 2;
      }
      :nth-child(8) ~ input {
        order: 3;
      }
      /* next label selected  will be from  7 + 4 */
    }
    <div class="container">
      <label>label1</label>
      <input placeholder="input1">
      <label>label2</label>
      <input placeholder="input2">
      <label>label3</label>
      <input placeholder="input3">
      <label>label4<br>lorem ipsum</label>
      <input placeholder="input4">
      <label>label5</label>
      <input placeholder="input5" style="height: 3em">
      <label>label6</label>
      <input placeholder="input6">
    </div>


    编辑,这是一个列 CSS 示例(关于我下面的评论)

    p input {
      display: block;
      width: 100%;
    }
    @media (min-width: 700px) {
      div {
        column-count: 2;
      }
    }
    <div class="container">
      <p><label>label1</label>
        <input placeholder="input1">
      </p>
      <p><label>label2</label>
        <input placeholder="input2">
      </p>
      <p><label>label3</label>
        <input placeholder="input3">
      </p>
      <p><label>label4<br>lorem ipsum</label>
        <input placeholder="input4">
      </p>
      <p><label>label5</label>
        <input placeholder="input5" style="height: 3em">
      </p>
      <p><label>label6</label>
        <input placeholder="input6">
      </p>
    </div>

    【讨论】:

      【解决方案4】:

      您需要在 flex div 中分别包装标签和输入,并在主 div 上使用 flex-direction: column。 不确定它是否已经在你的脑海中被点击并且我是显而易见的船长,但这就是我会做的。

      【讨论】:

      • 不幸的是,这不适用于不同的标签高度(参见标签 3 + 4)
      猜你喜欢
      • 1970-01-01
      • 2017-09-21
      • 1970-01-01
      • 2016-07-12
      • 2017-06-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-10
      相关资源
      最近更新 更多