
Спецификация 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. Это тоже может быть интересно: