Снова о 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 — по вертикали. Но бывает и иначе:

  1. В языках с другим направлением письма. В китайском и японском, например, строки идут по вертикали сверху вниз, а блоки — по горизонтали справа налево.
  2. В наших любимых флексбоксах! Не случайно именно в них с этими свойствами запутаться легче всего.

Во флексбоксах 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.

Выравнивание во флексбоксах

У флексбоксов есть несколько важных отличий, часто вызывающих путаницу:

  1. Контент группируется только по строкам. Внутри строк у флекс-элементов «свободы маневра» нет — их поджимают соседи. Даже растянуть вдоль главной оси их нельзя — за растягивание там отвечают подсвойства flex. Поэтому свойство justify-self для них (а значит — и justify-items для контейнера, ведь действуют они одинаково!) попросту не работают. Вот почему во флексбоксах мы знали только 4 свойства для выравнивания, и 2 из них были «без пары».
  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. Это тоже может быть интересно:

4

Комментарии

  1. Алексей

    Статья хорошая, но… немного затянутая. Когда относительно простую мысль начинаешь разжёвывать во всех возможных вариантах, она рискует превратится в сложную, потому что начинаешь терять нить того, где общий принцип начинает превращаться в частности, и где это действительно частности, а где они часть общего принципа.
    Наиболее тонкое место, на мой взгляд, вот это:
    «itemS — слово во множественном числе — выравнивает ЭЛЕМЕНТЫ по отдельности. Относительно того пространства, в котором у каждого из них есть «степень свободы». Например, в гриде это выравнивание каждого грид-элемента в его грид-области.»
    И, по-идее, и из дальнейшего изложения, понять, о какой степени свободы идёт речь, в принципе, не составляет большого труда, но дальнейшее понимание получается пониманием по-идее, а не по-сути. Потому что, если только с этим очень часто не имел дела, где контейнер колонки, а где её содержимое не так уж и очевидно. Хорошо бы именно в этом месте проиллюстрировать различие (если оно есть), для всех трёх вариантов: грида, флекса и обычного блока. И когда это станет ясным, достаточно очевидным, вероятно, будет и дальнейшее. Можно уже разобрать чем отличие выравнивания во флексбоксах: justify-items не работает(и self). (продольные и поперечные оси, тоже, но это уже частность мало имеющая отношения к общему принципу выравнивания). Ну и сказать как это теоретически может работать в обычных блоках (кстати, и, возможно, в колоночных контейнерах).
    А последнее предложение: » А justify-self для потомков и justify-items для контейнера работают так же, как в колонках.» меня почему-то загрузило. Каких колонках? Всё-таки статья не справочник, в ней не удобно и не сподручно искать готовый ответ на все случаи жизни, в ней нужен ясно изложенный проиллюстрированный принцип, из которого готовый ответ можно было приготовить самостоятельно. А, например, про блоки «По факту, грубо говоря, блок — это единственная колонка, всегда заполняющая всю ширину контейнера.» Хорошо. А высоту?
    Там же высота по содержимому. В общем, по блокам хорошо бы иллюстрацию картинкой.
    Иллюстрации по гридам и флексам мне понравились. Доходчивые и идею передают хорошо…

  2. Вальдемар

    Отличная, а самое главное актуальная статья.
    Спасибо, большое.

    P.S.: если не затруднит, напишите, пожалуйста, еще и по GridLS (Grid Layout System) статью.

  3. Yuzh

    Спасибо за статью!!!!!

  4. Anton Dubrovin

    Побольше бы такого материала! Спасибо за статью!

Оставить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Ваш E-mail не будет опубликован

Получать новые комментарии по электронной почте. Вы можете подписаться без комментирования.