Снова о CSS Box Alignment (свойствах для выравнивания всего): простая шпаргалка
Спецификация CSS Box Alignment становится всё более зрелой, и кроме шпаргалки по выравниванию блоков Рейчел Эндрю и нашего обзора свойств для выравнивания всего в сети появляются новые материалы о ней. Пожалуй, пришла пора и нам освежить знания об этих свойствах.
Общий принцип
Спецификация CSS Box Alignment предлагает 9 свойств для выравнивания всего. Все они состоят из двух частей и получаются комбинацией трех вариантов, что выравнивать, и трех вариантов, как выравнивать. Т.е. наши 9 свойств — это вот такая таблица 3×3:
Что выравнивать | ||||
Весь контент целиком | Элементы по отдельности (по умолчанию) | Один конкретный элемент | ||
Как выравнивать |
По строчной оси | justify-content |
justify-items |
justify-self |
По блочной оси | align-content |
align-items |
align-self |
|
По обеим осям сразу | place-content |
place-items |
place-self |
Как видим, вариантов не так уж много, но в похожих названиях легко запутаться. Разберемся, в чем между ними разница и что за что отвечает.
Как выравнивать: align
, justify
или place
?
Главная проблема — «куда justify
, а куда align
». Патрик Броссет в своей недавней статье предлагает запоминать, что justify
— это по той оси, по которой растягивает текст text-align: justify
(точнее, он упоминает аналогичную функцию «выравнивание по ширине» в Ворде; к сожалению, на русском она никак не созвучна слову «justify»).
Я предлагаю еще один прием для запоминания:
juSTify
— ключевые буквы СТ — значит, по СТрочной оси. А строчная ось — это как идут строки текста, слово за словом (в русском и английском — по горизонтали слева направо);aLign
— ключевая буква Л — значит, по бЛочной оси. А блочная ось — это как идут блоки текста, абзац за абзацем (в русском и английском — по вертикали сверху вниз).
Перепутать, по-моему, невозможно — ключевые буквы наоборот просто не вставляются:)
Ну а с place
всё просто — это просто комбинация align
+ justify
. Первым идет значение align
, вторым через пробел — значение justify
(можно сказать, в алфавитном порядке: A раньше J).
Для нас чаще всего justify
будет выравнивать по горизонтали, а align
— по вертикали. Но бывает и иначе:
- В языках с другим направлением письма. В китайском и японском, например, строки идут по вертикали сверху вниз, а блоки — по горизонтали справа налево.
- В наших любимых флексбоксах! Не случайно именно в них с этими свойствами запутаться легче всего.
Во флексбоксах juSTify
тоже работает по строкам, но это не строки текста, а строки флекс-элементов, или «flex lines» («гирлянды из ромашек» по меткой метафоре Чэнь Хуэй Цзин). И направление этих строк (во флексбоксах оно называется «главная ось») задается свойством flex-direction
, а порядок их друг за другом («поперечная ось») — свойством flex-wrap
. По умолчанию justify
— горизонтальное выравнивание, а align
— вертикальное, как обычно. Но при flex-direction: column
, эти оси «поменяются ролями» и align-*
станет горизонтальным выравниванием, а justify-*
— вертикальным.
В комментариях к нашей прошлой статье предложили еще неплохой вариант: justify
— это «продольные колебания», а align
— «поперечные». Возможно, вам окажется удобнее запомнить так.
Что выравнивать: content
, self
или items
?
Опять же, проще всего с self
. Он единственный применяется не к контейнеру, а к конкретному элементу. И выравнивает сам этот элемент («проверочное» слово — «селфи»:).
Остается выбор между content
и items
, которые оба применяются к контейнеру. На мой взгляд, удобнее всего запомнить так:
content
— слово в единственном числе — выравнивает весь КОНТЕНТ как одно целое. Относительно всего контейнера целиком. Если он во что-то собран, например, в колонки — то все эти колонки сразу, скопом. Если нет — и вовсе цельной кучей.itemS
— слово во множественном числе — выравнивает ЭЛЕМЕНТЫ по отдельности. Относительно того пространства, в котором у каждого из них есть «степень свободы». Например, в гриде это выравнивание каждого грид-элемента в его грид-области.
Фактически, items
для контейнера задает self
по умолчанию каждому элементу в этом контейнере. Поэтому и возможные значения, и результат их действия у items
для контейнера те же самые, что и у self
для отдельного элемента. Спецификация даже объединяет эти значения в группу
Короче говоря: content
для контейнера — выровнять контент целиком, self
для элемента — выровнять сам элемент, items
для контейнера — «self
оптом» всем элементам сразу.
Где выравнивать: в гридах, флексбоксах, многоколоночных контейнерах или обычных блоках?
В разных контекстах форматирования бывают свои нюансы выравнивания. Рассмотрим их поближе.
Выравнивание в гридах
Как ни странно, в гридах логика свойств выравнивания нагляднее и понятнее всего! Гриды двумерны и оба направления в них равноправны. Контент сгруппирован и по вертикали, и по горизонтали. Поэтому свойства *-content
выравнивают то, во что он сгруппирован:
justify-content
— группы по строчной оси, то есть колонки грида;align-content
— группы по по блочной оси, то есть ряды грида.
Ну а place-content
— просто сокращенная запись для align-content
и justify-content
одной строкой.
Свободное место по горизонтали можно оставить перед колонками (слева), после (справа), вокруг (отцентрировав их) или распределить его между ними. Все эти варианты мы видели в прошлой статье и во многих практических применениях гридов (в т.ч. в нашей задаче про равномерную отзывчивую сетку). По вертикали аналогично (хотя на практике, наверное, оставаться оно будет реже — высота чаще определяется контентом).
Свойства *-self
для каждого элемента грида выравнивают сам этот элемент в его грид-области:
justify-self
— по строчной оси (у нас — по горизонтали)align-self
— по блочной (у нас — по вертикали) соответственно.
И place-self
— просто сокращенная запись для align-self
и justify-self
.
Ну а justify-items
, align-items
и place-items
для контейнера — фактически просто способ задать «оптом» justify-self
, align-self
и place-self
по умолчанию для всех его элементов.
Можете еще раз посмотреть интерактивный пример из прошлой статьи, а также еще один пример, наглядно показывающий разницу между выравниванием всего контента и отдельных элементов (наводите на свойство и смотрите анимацию его действия):
See the Pen Пример действия свойств выравнивания в гридах by Ilya Streltsyn (@SelenIT) on CodePen.
Выравнивание во флексбоксах
У флексбоксов есть несколько важных отличий, часто вызывающих путаницу:
- Контент группируется только по строкам. Внутри строк у флекс-элементов «свободы маневра» нет — их поджимают соседи. Даже растянуть вдоль главной оси их нельзя — за растягивание там отвечают подсвойства
flex
. Поэтому свойствоjustify-self
для них (а значит — иjustify-items
для контейнера, ведь действуют они одинаково!) попросту не работают. Вот почему во флексбоксах мы знали только 4 свойства для выравнивания, и 2 из них были «без пары». - Направления осей могут отличаться от направления текста (и это единственный случай, когда специальные флексбоксовые значения
flex-start
иflex-end
отличаются от универсальныхstart
иend
).
Поскольку направления во флексбоксах неравноправны и по главной оси флекс-элементы никак не группирутся, свойства *-content
там действуют на разные объекты:
align-content
— на группы («строки») флекс-элементов. Будьте внимательны — они бывают и вертикальными;justify-content
— на отдельные флекс-элементы в каждой строке!
Внимание: если флексбокс однострочный (flex-wrap: nowrap
), то его единственная строка всегда считается растянутой на всю высоту контейнера, и align-content
не дает никакого эффекта.
А выравнивание элементов по поперечной оси (align-self
для каждого в отдельности и align-items
контейнера — для всех сразу по умолчанию) работает аналогично выравниванию рядов грида и элементов в рядах. Разве что отлаживать его труднее: браузерные отладчики пока не показывают, где заканчиваются строки флекс-элементов, так что приходится держать их «в уме» (и отслеживать по самому «толстому» флекс-элементу в каждой строке). В примере ниже они искусственно подсвечены для наглядности. Как и в предыдущем примере, наводите на свойство и смотрите анимацию его действия:
See the Pen Пример действия свойств выравнивания во флексбоксах by Ilya Streltsyn (@SelenIT) on CodePen.
Выравнивание в многоколоночных контейнерах
Предупреждение: в этом разделе описано, как это должно работать по спецификации. В сегодняшних браузерах это пока, увы, не работает (не забывайте голосовать за исправление соотв. багов!). Поэтому даже пример приводить пока нет большого смысла (но позже мы обязательно обновим статью и добавим его).
Как и флексбоксы, CSS-колонки — несимметричная система раскладки. Только группируется контент, наоборот, лишь по колонкам, а контент внутри колонок «свален в кучу». Поэтому свойства *-content
там тоже действуют на разные объекты:
justify-content
— на сами колонки;align-content
— на содержимое каждой колонки как единое целое.
Распределять колонки по горизонтали можно всеми способами (к началу контейнера, к концу, по центру, с растягиванием промежутков…), контент внутри колонок можно только сдвигать целиком к началу, концу или центру, но растягивать нельзя.
Колонки — не какой-то особый контекст форматирования, а обычный блочный, просто разбитый на фрагменты. Так что их потомки — обычные блоки. Выровнять отдельный блок по вертикали нельзя (по той же причине, по которой нельзя выровнять флекс-элемент по главной оси — нет «свободы маневра», двигать элемент не дают его соседи). Поэтому align-self
для потомков и align-items
для контейнера там и не должны работать. Зато должны работать justify-self
для потомков (и, соответственно, justify-items
для контейнера) — прижимая блоки к левому или правому краю колонки, центрируя их или растягивая на всю ширину.
Выравнивание в блоках
Предупреждение: этот раздел пока тоже чисто теоретический (увы!) и на практике, чтобы выровнять что-то по центру блока, лучше сразу делать этот блок флекс- или грид-контейнером. Поэтому смотреть пока тоже не на что, можно лишь вкратце ознакомиться с самими правилами.
По факту, грубо говоря, блок — это единственная колонка, всегда заполняющая всю ширину контейнера. Поэтому по строчной оси там двигать нечего и justify-content
работать не будет. Но align-content
будет двигать весь контент блока как единое целое (если в нем будет запас по высоте).
Свойства align-self
для потомков и align-items
для контейнера в блоке тоже не работают (как и в колонках, по той же причине). А justify-self
для потомков и justify-items
для контейнера работают так же, как в колонках.
P.S. Это тоже может быть интересно:
Статья хорошая, но… немного затянутая. Когда относительно простую мысль начинаешь разжёвывать во всех возможных вариантах, она рискует превратится в сложную, потому что начинаешь терять нить того, где общий принцип начинает превращаться в частности, и где это действительно частности, а где они часть общего принципа.
Наиболее тонкое место, на мой взгляд, вот это:
«itemS — слово во множественном числе — выравнивает ЭЛЕМЕНТЫ по отдельности. Относительно того пространства, в котором у каждого из них есть «степень свободы». Например, в гриде это выравнивание каждого грид-элемента в его грид-области.»
И, по-идее, и из дальнейшего изложения, понять, о какой степени свободы идёт речь, в принципе, не составляет большого труда, но дальнейшее понимание получается пониманием по-идее, а не по-сути. Потому что, если только с этим очень часто не имел дела, где контейнер колонки, а где её содержимое не так уж и очевидно. Хорошо бы именно в этом месте проиллюстрировать различие (если оно есть), для всех трёх вариантов: грида, флекса и обычного блока. И когда это станет ясным, достаточно очевидным, вероятно, будет и дальнейшее. Можно уже разобрать чем отличие выравнивания во флексбоксах: justify-items не работает(и self). (продольные и поперечные оси, тоже, но это уже частность мало имеющая отношения к общему принципу выравнивания). Ну и сказать как это теоретически может работать в обычных блоках (кстати, и, возможно, в колоночных контейнерах).
А последнее предложение: » А justify-self для потомков и justify-items для контейнера работают так же, как в колонках.» меня почему-то загрузило. Каких колонках? Всё-таки статья не справочник, в ней не удобно и не сподручно искать готовый ответ на все случаи жизни, в ней нужен ясно изложенный проиллюстрированный принцип, из которого готовый ответ можно было приготовить самостоятельно. А, например, про блоки «По факту, грубо говоря, блок — это единственная колонка, всегда заполняющая всю ширину контейнера.» Хорошо. А высоту?
Там же высота по содержимому. В общем, по блокам хорошо бы иллюстрацию картинкой.
Иллюстрации по гридам и флексам мне понравились. Доходчивые и идею передают хорошо…
Отличная, а самое главное актуальная статья.
Спасибо, большое.
P.S.: если не затруднит, напишите, пожалуйста, еще и по GridLS (Grid Layout System) статью.
Спасибо за статью!!!!!
Побольше бы такого материала! Спасибо за статью!
Вы бы только знали, как сильно выручили. Мерси.