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

5

Комментарии

  1. Алексей

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

  2. Вальдемар

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

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

  3. Yuzh

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

  4. Anton Dubrovin

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

  5. Renton

    Вы бы только знали, как сильно выручили. Мерси.

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

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

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

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