Об авторе: Рэйчел Эндрю — не только главный редактор журнала Smashing Magazine, но и веб-разработчик, писатель и спикер. Она автор ряда книг, в том числе The New CSS Layout, один из разработчиков системы управления контентом Perch. Пишет о бизнесе и технологиях на своём сайте rachelandrew.co.uk.

Краткое содержание: в этой статье мы рассмотрим свойства выравнивания во Flexbox и некоторые основные правила, как работает выравнивание по основной и поперечной осям.

В первой статье этого цикла я рассказала, что происходит при объявлении свойства display: flex для элемента. Сейчас рассмотрим свойства выравнивания и как они работают с Flexbox. Если вы когда-либо приходили в замешательство, применить align или justify, надеюсь, эта статья многое прояснит!

История выравнивания во Flexbox


За всю историю CSS правильное выравнивание по обеим осям казалось самой сложной проблемой. Появление этой функции во Flexbox для многих стало главным преимуществом этой технологии. Выравнивание свелось к двум строчкам CSS.

Свойства выравнивания теперь полностью определены в спецификации Box Alignment. Она детализирует, как работает выравнивание в различных макетах. Это означает, что в CSS Grid можно использовать те же свойства, что и в Flexbox — а в будущем в других макетах тоже. Поэтому любая новая функция выравнивания Flexbox будет подробно описана в спецификации Box Alignment, а не в следующей версии Flexbox.

Свойства


Многим трудно запомнить, следует ли использовать свойства, которые начинаются с align- или с justify-. Важно помнить следующее:

  • justify- выполняет выравнивание по главной оси в том же направлении, что и flex-direction;
  • align- выполняет выравнивание по оси поперёк направлению flex-direction.

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

Выравнивание главной оси с помощью justify-content


Начнём с выравнивания по главной оси. Оно осуществляется с помощью свойства justify-content. Данное свойство обрабатывает все элементы как группу и управляет распределением пространства между ними.

Изначальное значение justify-content равняется flex-start. Вот почему при объявлении display: flex все элементы flex выстраиваются в начале строки. В письменности слева направо элементы группируются слева.


Обратите внимание, что свойство justify-content производит видимый эффект только при наличии свободного места. Поэтому если у вас набор элементов занимает всё пространство на главной оси, justify-content ничего не даст.


Если указать для justify-content значение flex-end, то все элементы переместятся в конец строки. Свободное место теперь находится в начале.


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


Мы можем распределить пространство с помощью justify-content: space-around. В этом случае доступное пространство делится на равные части и помещается с каждой стороны элемента.


Новое значение justify-content можно найти в спецификации Box Alignment; оно не указано в спецификации Flexbox. Это значение space-evenly. В этом случае элементы равномерно распределяются в контейнере, а дополнительное пространство поровну распределяется между элементами и с обеих сторон.



Вы можете поиграться со всеми значениями в демо.

Значения точно так же работают по вертикали, то есть если flex-direction применяется для column. Правда, у вас в столбце может не оказаться свободного места для распределения, если не добавить высоту или block-size контейнера, как в этом демо.

Выравнивание по осям с помощью align-content


Если в контейнере несколько осей и указано flex-wrap: wrap, то можно использовать align-content для выравнивания строк на поперечной оси. Но требуется дополнительное пространство. В этой демонстрации поперечная ось работает в направлении колонки, и я указала высоту контейнера 60vh. Поскольку это больше, чем необходимо для отображения всех элементов, то появляется свободное пространство по вертикали.

Затем я могу применить align-content с любым из значений.

Если в качестве flex-direction указано column, то align-content работает как в следующем примере.

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

Свойство по place-content


В спецификации Box Alignment можно найти свойство place-content. Использование этого свойства означает, что вы одновременно устанавливаете justify-content и align-content. Первое значение — для align-content, второе для justify-content. Если задано только одно значение, то оно применяется к обоим свойствам:

.container {
    place-content: space-between stretch;
}

Соответствует этому:

.container {
    align-content: space-between; 
    justify-content: stretch;
}

А такой код:

.container {
    place-content: space-between;
}

Равноценен следующему:

.container {
    align-content: space-between; 
    justify-content: space-between;
}

Выравнивание по осям с помощью align-items


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


Как вариант, её можно определить свойством height в контейнере:


Почему элементы растягиваются до размера самого высокого элемента — это потому что начальным значением параметра align-items является stretch. Элементы растягиваются по поперечной оси до размера контейнера в этом направлении.

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

Кроме начального значения stretch, можно присвоить элементам align-items значение flex-start, в этом случае они выравниваются по началу контейнера и больше не растягиваются по высоте.


Значение flex-end перемещает их в конец контейнера по поперечной оси.


Если вы используете значение center, то элементы центрируются относительно друг друга:


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


Все эти варианты можно попробовать в демо.

Индивидуальное выравнивание с помощью align-self


Свойство align-items задаёт выравнивание всех элементов одновременно. В действительности оно устанавливает значения align-self для всех элементов группы. Можно также использовать свойство align-self для любого отдельного элемента, чтобы выровнять его внутри строки и относительно других элементов.

В следующем примере в контейнере используется align-items для выравнивания всей группы по центру, но также align-self для первого и последнего элементов.



Почему нет justify-self?


Часто возникает вопрос, почему невозможно выровнять один элемент или группу элементов по главной оси. Почему во Flexbox нет свойства -self для выравнивания по главной оси? Если вы представите justify-content и align-content как способ распределения пространства, то ответ становится более очевидным. Мы имеем дело с элементами как с группой и размещаем свободное пространство определённым образом: либо в начале, либо в конце группы, либо между элементами.

Также может быть полезно подумать, как justify-content и align-content работают в CSS Grid Layout. В Grid эти свойства используются для распределения свободного пространства в grid-контейнере между grid-дорожками. Здесь тоже мы берём группу дорожек — и с помощью этих свойств распределяем между ними свободное пространство. Поскольку мы оперируем в группе и в Grid, и во Flexbox, то не можем взять отдельный элемент и сделать с ним что-то другое. Тем не менее, есть способ получить оформление макета, которое хотят верстальщики, когда говорят о свойстве self на главной оси. Это использование автоматических полей.

Использование автоматических полей на основной оси


Если вы когда-нибудь центрировали блок в CSS (например, враппер для контента главной страницы, установив поля слева и справа в auto), то у вас уже есть некоторый опыт работы с автоматическими полями. Значение auto для полей заполняет максимальное пространство в установленном направлении. Для центрирования блока мы устанавливаем и левое, и правое поля в auto: каждое из них пытается занять как можно больше места, и поэтому помещает наш блок в центр.

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

Берём этот элемент и указываем для свойства margin-left значение auto. Это значит, что поле пытается получить как можно больше места слева от элемента, то есть элемент выталкивается к правой границе.



Если вы используете автоматические поля на главной оси, то justify-content перестанет действовать, так как автоматические поля займут всё пространство, которое в противном случае распределялось бы с помощью justify-content.

Запасное выравнивание


Для каждого метода выравнивания описан запасной вариант — что произойдёт, если заданное выравнивание невозможно. Например, если у вас есть только один элемент в контейнере, а вы указали justify-content: space-between, что должно произойти? В этом случае применяется запасное выравнивание flex-start — один элемент будет выровнен по началу контейнера. В случае justify-content: space-around используется запасное выравнивание center.

В текущей спецификации вы не можете изменить запасное выравнивание. Есть примечание к спецификациям, которое допускает возможность указания произвольного запасного варианта в будущих версиях.

Безопасное и небезопасное выравнивание


Недавним дополнением к спецификации Box Alignment стала концепция безопасного и небезопасного выравнивания с использованием ключевых слов safe и unsafe.

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

.container {  
    display: flex;
    flex-direction: column;
    width: 100px;
    align-items: unsafe center;
}

.item:last-child {
    width: 200px;
}


Безопасное выравнивание предотвращает потерю данных, перемещая переполнение на другую сторону.

.container {  
    display: flex;
    flex-direction: column;
    width: 100px;
    align-items: safe center;
}

.item:last-child {
    width: 200px;
}


Эти ключевые слова пока поддерживаются не всеми браузерами, однако демонстрируют, как спецификации Box Alignment добавляют контроля во Flexbox.

Заключение


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

  • justify- для основных осей, а align- для поперечных;
  • для align-content и justify-content требуется свободное пространство;
  • свойства align-content и justify-content применяются к элементам в группе, распределяя пространство между ними. Нельзя указывать выравнивание отдельного элемента, потому что свойство -self отсутствует;
  • если хотите выровнять один элемент или разбить группу по основной оси, используйте автоматические поля;
  • align-items устанавливает одинаковые свойства align-self для всей группы. Используйте align-self для дочернего элемента группы, чтобы установить ему значение индивидуально.

Комментарии (3)


  1. BerkutEagle
    22.08.2018 17:20

    с использованием безопасных и небезопасных ключевых слов.

    Может с использованием ключевых слов safe и unsafe?
    Или действительно есть небезопасные ключевые слова? :)


    1. m1rko Автор
      22.08.2018 17:39

      Точно! :)


  1. profesor08
    23.08.2018 20:54

    Вот бы IE испарился. А то он еще текущую реализацию еле переваривает, а тут скоро новая.