В 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>
На момент написания статьи нет упоминания о 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 вдоль главной оси:
-
justify-content
свойство ключевого слова и 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
,
Я думаю, что это новая функция. Совместимость браузера несколько не хватает.