Лучший способ организовать ярлыки и входы бок о бок

Без использования таблиц или display:table, возможно ли иметь гибкую область ширины для меток слева от входов? Я также хотел бы избежать макета сетки для соображений совместимости браузера. Я бы хотел, чтобы css позаботился об этом:

short_label   input_box____________________
tiny_label    input_box____________________
medium_label  input_box____________________

И затем также обрабатывайте большие ярлыки соответственно:

short_label            input_box__________
medium_label           input_box__________
very_extra_long_label  input_box__________

Но я не хочу:

short_label            input_box__________
tiny_label             input_box__________
medium_label           input_box__________

Итак, первый столбец должен иметь гибкую ширину, а второй столбец должен расти, чтобы заполнить пробел. Мой html идеально выглядел бы как-то вроде этого, но при необходимости можно было бы добавить div-строки. Я чувствую, что есть гибкий ответ, но, возможно, нет, поскольку все строки должны быть выровнены.

<div class='aligned_form'>

  <label for='a'>short_label</label>
  <input type='text' id='a'>

  <label for='b'>medium_label</label>
  <input type='text' id='b'>

  <label for='c'>very_extra_long_label</label>
  <input type='text' id='c'>

</div>

Ответы

Ответ 1

align-items: stretch

Flexbox имеет функцию, обычно известную как "столбцы с равной высотой". Эта функция позволяет гибким элементам в одном контейнере иметь равную высоту.

Эта функция исходит из двух исходных настроек:

  • flex-direction: row
  • align-items: stretch

С небольшой модификацией эта функция может стать "рядами равной ширины".

  • flex-direction: column
  • align-items: stretch

Теперь столбец гибких элементов будет иметь ширину самого длинного элемента.

Ссылка:


align-content: stretch

Исходная настройка в контейнере гибкости align-content: stretch. Этот параметр будет распределять строки или столбцы (в зависимости от flex-direction) по длине контейнера.

В этом случае, чтобы упаковать два столбца в начало контейнера, мы должны переопределить значение по умолчанию с помощью align-content: flex-start.

Литература:


flex-direction: column, flex-wrap: wrap и height

Поскольку у вас есть предпочтительная структура HTML (со всеми элементами формы, логически упорядоченными в одном контейнере), гибкие элементы необходимо обернуть, чтобы сформировать столбец меток и столбец входов.

Поэтому нам нужно переопределить flex-wrap: nowrap (по умолчанию) с помощью wrap.

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

Литература:


Свойство order

Свойство order необходимо для правильного выравнивания меток и входов между столбцами.

Ссылка:


.aligned_form {
  display: flex;
  flex-flow: column wrap;
  align-content: flex-start;
  height: 75px;
}

label[for='a'] { order: -3; }
label[for='b'] { order: -2; }
label[for='c'] { order: -1; }

label, input {
  height: 25px;
  padding: 5px;
  box-sizing: border-box;
}
<!-- No changes to the HTML. -->

<div class='aligned_form'>

  <label for='a'>short_label</label>
  <input type='text' id='a' placeholder="short_label">

  <label for='b'>medium_label</label>
  <input type='text' id='b' placeholder="medium_label">

  <label for='c'>very_extra_long_label</label>
  <input type='text' id='c' placeholder="very_extra_long_label">

</div>

Ответ 2

Я знаю, что вы сказали, что не хотите компоновки CSS Grid, но я собираюсь добавить его здесь для целей документации. Как я считаю, это самый чистый из решений, если вы не против проблем с поддержкой.

Вы всегда можете установить фиксированную ширину для входов, заменив 1fr на пиксель или другое значение. Кроме того, align-self центрирует метку и вводит ее вертикально, если вы хотите, чтобы нижнее выравнивание изменилось center на end. Это также делает HTML слишком чистым!

.container{
  display: grid;
  grid-gap: 10px;
  grid-template-columns: [label] auto [input] 1fr;
}
input {
  grid-column: input;
  align-self: center;
}
label {
  grid-column: label;
  align-self: center;
}
<div class="container">
      <label for='a'>short_label</label>
      <input type='text' id='a'>

      <label for='b'>medium_label</label>
      <input type='text' id='b'>

      <label for='c'>very_extra_long_label</label>
      <input type='text' id='c'>
</div>

Ответ 3

Я думаю, что решение @Michael_B велико, но другим способом было бы создать строку flex с двумя столбцами, а затем сделать каждый столбец столбцом flex. Просто установите высоту на label/input, чтобы они были согласованы и отрегулировали поля.

<link href="#" onclick="location.href='https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-alpha.6/css/bootstrap.min.css'; return false;" rel="stylesheet"/>

<style>
label,input {
  height: 25px;
  margin:0 0 .5em;
}
label {
  margin-right: .5em;
}
</style>

<div class="container">
  <div class="row">
    <div class="d-flex flex-column">
      <label for='a'>short_label</label>
      <label for='b'>medium_label</label>
      <label for='c'>very_extra_long_label</label>
    </div>
    <div class="d-flex flex-column">
      <input type='text' id='a'>
      <input type='text' id='b'>
      <input type='text' id='c'>
    </div>
  </div>
</div>