В CSS Flexbox, почему нет свойств "justify-items" и "justify-self"?

Рассмотрим основную ось и поперечную ось гибкого контейнера:

Источник: W3C

Для выравнивания гибких элементов вдоль главной оси есть одно свойство:

  • justify-content

Для выравнивания изгибаемых элементов вдоль поперечной оси есть три свойства:

  • align-content
  • align-items
  • align-self

На изображении выше главная ось горизонтальная, а поперечная ось вертикальная. Это стандартные направления гибкого контейнера.

Тем не менее, эти направления могут быть легко взаимозаменяемы с flex-direction имущество.

/* main axis is horizontal, cross axis is vertical */
flex-direction: row;
flex-direction: row-reverse;

/* main axis is vertical, cross axis is horizontal */    
flex-direction: column;
flex-direction: column-reverse;

(Ось креста всегда перпендикулярна главной оси.)

Моя точка зрения при описании работы осей заключается в том, что в обоих направлениях нет ничего особенного. Главная ось, поперечная ось, они оба равны с точки зрения важности и flex-direction позволяет легко переключаться вперед и назад.

Так почему же поперечная ось получает два дополнительных свойства выравнивания?

Почему align-content а также align-items объединены в одно свойство для главной оси?

Почему главная ось не получает justify-self имущество?


Сценарии, где эти свойства будут полезны:

  • размещение гибкого элемента в углу гибкого контейнера
    #box3 { align-self: flex-end; justify-self: flex-end; }

  • Выравнивание группы элементов Flex по правому краю (justify-content: flex-end) но выровнять первый элемент по левому краю (justify-self: flex-start)

    Рассмотрим заголовок раздела с группой элементов навигации и логотипом. С justify-self логотип может быть выровнен по левому краю, в то время как навигационные элементы остаются далеко вправо, и все это плавно регулируется ("сгибается") к разным размерам экрана.

  • в ряду из трех элементов flex прикрепите средний элемент к центру контейнера (justify-content: center) и выровняйте соседние элементы по краям контейнера (justify-self: flex-start а также justify-self: flex-end).

    Обратите внимание, что значения space-around а также space-between на justify-content Свойство не будет сохранять средний элемент по центру относительно контейнера, если смежные элементы имеют разную ширину.

#container {
  display: flex;
  justify-content: space-between;
  background-color: lightyellow;
}
.box {
  height: 50px;
  width: 75px;
  background-color: springgreen;
}
.box1 {
  width: 100px;
}
.box3 {
  width: 200px;
}
#center {
  text-align: center;
  margin-bottom: 5px;
}
#center > span {
  background-color: aqua;
  padding: 2px;
}
<div id="center">
  <span>TRUE CENTER</span>
</div>

<div id="container">
  <div class="box box1"></div>
  <div class="box box2"></div>
  <div class="box box3"></div>
</div>

<p>note that the middle box will only be truly centered if adjacent boxes are equal width</p>

версия jsFiddle


На момент написания статьи нет упоминания о justify-self или же justify-items в спецификации flexbox.

Однако в модуле выравнивания блоков CSS, который является незаконченным предложением W3C по созданию общего набора свойств выравнивания для использования во всех блочных моделях, есть следующее:

Источник: W3C

Вы заметите, что justify-self а также justify-items рассматриваются... но не для flexbox.


В заключение я повторю главный вопрос:

Почему отсутствуют свойства "justify-items" и "justify-self"?

5 ответов

Решение

Методы выравнивания изгибаемых элементов вдоль главной оси

Как указано в вопросе:

Для выравнивания гибких элементов вдоль главной оси есть одно свойство: justify-content

Для выравнивания изгибаемых элементов вдоль поперечной оси есть три свойства: align-content, align-items а также align-self,

Затем возникает вопрос:

Почему нет justify-items а также justify-self свойства?

Один ответ может быть: потому что они не нужны.

Спецификация flexbox предоставляет два метода выравнивания элементов flex вдоль главной оси:

  1. justify-content свойство ключевого слова и
  2. auto поля

обосновывать-контент

justify-content Свойство выравнивает элементы flex вдоль главной оси контейнера flex.

Он применяется к гибкому контейнеру, но влияет только на гибкие элементы.

Есть пять вариантов выравнивания:

  • flex-start Гибкие элементы упакованы в начале линии.

  • flex-end Гибкие элементы упакованы в конце линии.

  • center Гибкие элементы упакованы по направлению к центру линии.

  • space-between Элементы Flex расположены равномерно, первый элемент выровнен по одному краю контейнера, а последний элемент - по противоположному краю. Края, используемые первыми и последними элементами, зависят от flex-direction и режим записи (ltr или же rtl).

  • space-around ~ Так же, как space-between кроме как с половинными пробелами на обоих концах.


Авто наценки

С auto поля, гибкие элементы могут быть отцентрированы, разнесены или упакованы в подгруппы.

В отличие от justify-content, который применяется к гибкому контейнеру, auto поля идут на гибких элементах.

Они работают, потребляя все свободное пространство в указанном направлении.


Выровняйте группу изгибаемых элементов справа, но первый элемент слева

Сценарий из вопроса:

  • Выравнивание группы элементов Flex по правому краю (justify-content: flex-end) но выровнять первый элемент по левому краю (justify-self: flex-start)

    Рассмотрим заголовок раздела с группой элементов навигации и логотипом. С justify-self логотип может быть выровнен по левому краю, в то время как навигационные элементы остаются далеко вправо, и все это плавно регулируется ("сгибается") к разным размерам экрана.


Другие полезные сценарии:


Поместите гибкий элемент в угол

Сценарий из вопроса:

  • размещение гибкого элемента в углу .box { align-self: flex-end; justify-self: flex-end; }


Центрируйте гибкий элемент по вертикали и горизонтали

margin: auto является альтернативой justify-content: center а также align-items: center,

Вместо этого кода в контейнере flex:

.container {
    justify-content: center;
    align-items: center;
}

Вы можете использовать это на элементе flex:

.box56 {
    margin: auto;
}

Эта альтернатива полезна при центрировании гибкого элемента, который переполняет контейнер.


Отцентрируйте гибкий элемент и отцентрируйте второй гибкий элемент между первым и краем

Гибкий контейнер выравнивает гибкие элементы, распределяя свободное пространство.

Следовательно, чтобы создать равный баланс, чтобы средний элемент мог быть центрирован в контейнере с одним элементом рядом, необходимо ввести противовес.

В приведенных ниже примерах невидимые третьи гибкие элементы (вставки 61 и 68) представлены для уравновешивания "реальных" предметов (вставки 63 и 66).

Конечно, этот метод не является чем-то большим с точки зрения семантики.

В качестве альтернативы вы можете использовать псевдоэлемент вместо фактического элемента DOM. Или вы можете использовать абсолютное позиционирование. Здесь рассматриваются все три метода: гибкий и центральный элементы

ПРИМЕЧАНИЕ. Приведенные выше примеры будут работать - с точки зрения истинного центрирования - только когда самые внешние элементы равны высоте / ширине. Когда гибкие элементы имеют разную длину, см. Следующий пример.


Центрируйте гибкий элемент, когда соседние элементы различаются по размеру

Сценарий из вопроса:

  • в ряду из трех элементов flex прикрепите средний элемент к центру контейнера (justify-content: center) и выровняйте соседние элементы по краям контейнера (justify-self: flex-start а также justify-self: flex-end).

    Обратите внимание, что значения space-around а также space-between на justify-content Свойство не будет держать средний элемент по центру относительно контейнера, если соседние элементы имеют разную ширину ( см. демонстрацию).

Как уже отмечалось, если только все гибкие элементы не имеют одинаковую ширину или высоту (в зависимости от flex-direction), средний элемент не может быть действительно центрирован. Эта проблема дает веские основания для justify-self собственность (предназначена для решения задачи, конечно).

#container {
  display: flex;
  justify-content: space-between;
  background-color: lightyellow;
}
.box {
  height: 50px;
  width: 75px;
  background-color: springgreen;
}
.box1 {
  width: 100px;
}
.box3 {
  width: 200px;
}
#center {
  text-align: center;
  margin-bottom: 5px;
}
#center > span {
  background-color: aqua;
  padding: 2px;
}
<div id="center">
  <span>TRUE CENTER</span>
</div>

<div id="container">
  <div class="box box1"></div>
  <div class="box box2"></div>
  <div class="box box3"></div>
</div>

<p>The middle box will be truly centered only if adjacent boxes are equal width.</p>

Вот два способа решения этой проблемы:

Решение № 1: Абсолютное позиционирование

Спецификация flexbox обеспечивает абсолютное позиционирование элементов flex. Это позволяет центрировать средний элемент независимо от размера его братьев и сестер.

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

В приведенных ниже примерах средний элемент центрируется с абсолютным позиционированием, а внешние элементы остаются в потоке. Но тот же самый макет может быть достигнут в обратном порядке: центрируйте средний элемент с помощью justify-content: center и абсолютно позиционируйте внешние предметы.

Решение № 2: Вложенные Flex-контейнеры (без абсолютного позиционирования)

.container {
  display: flex;
}
.box {
  flex: 1;
  display: flex;
  justify-content: center;
}
.box71 > span { margin-right: auto; }
.box73 > span { margin-left: auto;  }

/* non-essential */
.box {
  align-items: center;
  border: 1px solid #ccc;
  background-color: lightgreen;
  height: 40px;
}
<div class="container">
  <div class="box box71"><span>71 short</span></div>
  <div class="box box72"><span>72 centered</span></div>
  <div class="box box73"><span>73 loooooooooooooooong</span></div>
</div>

Вот как это работает:

  • Div верхнего уровня (.container) представляет собой гибкий контейнер.
  • Каждый ребенок div (.box) теперь гибкий элемент.
  • каждый .box пункт дан flex: 1 для равномерного распределения пространства контейнера.
  • Теперь элементы занимают все пространство в строке и имеют одинаковую ширину.
  • Сделайте каждый элемент (вложенным) гибким контейнером и добавьте justify-content: center,
  • Теперь каждый span Элемент является центрированным гибким элементом.
  • Используйте flex auto поля для смещения внешнего span с левой и правой.

Вы также можете отказаться justify-content и использовать auto поля исключительно.

Но justify-content может работать здесь, потому что auto поля всегда имеют приоритет. Из спецификации:

8.1. Выравнивание с auto поля

До выравнивания через justify-content а также align-self любое положительное свободное пространство распределяется по автоматическим полям в этом измерении.


justify-content: space-same (концепция)

Возвращаясь к justify-content на минуту, вот идея еще одного варианта.

  • space-same ~ Гибрид space-between а также space-around, Flex элементы расположены равномерно (например, space-between), за исключением того, что вместо половинных пробелов на обоих концах (как space-around), есть полноразмерные пространства на обоих концах.

Этот макет может быть достигнут с ::before а также ::after псевдоэлементы на гибком контейнере.

(кредит: @oriol для кода и caub для метки)

ОБНОВЛЕНИЕ: Браузеры начали реализацию space-evenly, что завершает вышесказанное. Смотрите этот пост для деталей: Равное пространство между гибкими элементами


PLAYGROUND (включает код для всех примеров выше)

Я знаю, что это не ответ, но я бы хотел внести свой вклад в этот вопрос, чтобы он того стоил. Было бы здорово, если бы они могли выпустить justify-self для flexbox, чтобы сделать его действительно гибким.

Я считаю, что когда на оси несколько элементов, наиболее логичным justify-self вести себя означает выравниваться с ближайшими соседями (или ребром), как показано ниже.

Я искренне надеюсь, что W3C это заметит и, по крайней мере, рассмотрит. знак равно

введите описание изображения здесь

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

введите описание изображения здесь

Простота создания потрясающих макетов бесконечна, взгляните на этот "сложный" пример.

введите описание изображения здесь

Это было задано в списке в стиле www, и Таб Аткинс (редактор спецификаций) дал ответ, объясняющий почему. Я подробно остановлюсь здесь.

Для начала давайте предположим, что наш flex-контейнер является однострочным (flex-wrap: nowrap). В этом случае очевидно, что существует разница в выравнивании между главной осью и поперечной осью - на главной оси есть несколько элементов, уложенных друг на друга, но только один элемент расположен на поперечной оси. Так что имеет смысл иметь настраиваемое для каждого элемента "align-self" на поперечной оси (поскольку каждый элемент выравнивается отдельно), тогда как на главной оси это не имеет смысла (так как там пункты выровнены все вместе).

Для многострочного flexbox та же логика применяется к каждой "гибкой линии". В данной строке элементы выровнены по отдельности по перекрестной оси (поскольку в поперечной оси имеется только один элемент на линию), а по основной оси - все вместе.


Вот еще один способ сформулировать это: так, все *-self а также *-content свойства о том, как распределить дополнительное пространство вокруг вещей. Но ключевое отличие в том, что *-self версии для случаев, когда есть только одна вещь на этой оси, и *-content версии для тех случаев, когда на этой оси потенциально много вещей. Сценарии "одно против многих" - это разные типы проблем, поэтому у них есть разные типы опций - например, space-around / space-between значения имеют смысл для *-content, но не для *-self,

SO: На главной оси flexbox есть много вещей, которые нужно распределять вокруг. Так что *-content собственность имеет смысл там, но не *-self имущество.

В противоположность этому, в поперечной оси мы имеем *-self и *-content имущество. Один определяет, как мы будем распределять пространство вокруг множества гибких линий (align-content), тогда как другой (align-self) определяет, как распределить пространство вокруг отдельных изгибаемых элементов на поперечной оси в пределах данной линии изгиба.

(Я игнорирую *-items свойства здесь, так как они просто устанавливают значения по умолчанию для *-self.)

Я только что нашел собственное решение этой проблемы, или, по крайней мере, свою проблему.
Я использовалjustify-content: space-around вместо того justify-content: space-between;.

Таким образом, конечные элементы будут оставаться сверху и снизу, и у вас могут быть собственные поля, если вы хотите.

Я знаю, что здесь не используется flexbox, но для простого случая использования трех элементов (один слева, один в центре, один справа) это можно легко сделать, используя display: grid на родителя, grid-area: 1/1/1/1; на детей, и justify-self для позиционирования тех детей.

<div style="border: 1px solid red; display: grid; width: 100px; height: 25px;">
  <div style="border: 1px solid blue; width: 25px; grid-area: 1/1/1/1; justify-self: left;"></div>
  <div style="border: 1px solid blue; width: 25px; grid-area: 1/1/1/1; justify-self: center;"></div>
  <div style="border: 1px solid blue; width: 25px; grid-area: 1/1/1/1; justify-self: right;"></div>
</div>

Есть justify-self, но в Chrome Canary, а не в стабильной версии Chrome. Есть даже justify-items:

Но, насколько я могу судить, эти свойства тоже не работают. Так что, вероятно, Google сохранил его заранее для будущих релизов CSS. Можно только надеяться, что они добавят свойства в ближайшее время.

Есть justify-items,

Я думаю, что это новая функция. Совместимость браузера несколько не хватает.

Другие вопросы по тегам