align-items выравнивает flex-элементы вдоль поперечной оси - той, что перпендикулярна направлению, заданному flex-direction. По умолчанию элементы растягиваются на всю поперечную ось (stretch), но можно прижать их к одному краю, к центру или выровнять по базовой линии текста значением baseline.
В этом уроке
Попробуй прямо сейчас: замени align-items: center на flex-start, потом на stretch - обрати внимание, что при stretch все три блока разной заданной высоты станут одинаковыми, растянувшись на всю высоту контейнера.
Пять значений align-items: stretch, flex-start, flex-end, center, baseline
Поперечную ось определяет flex-direction - об этом уже говорилось в уроке про направление flex-элементов: при row поперечная ось вертикальна, при column - горизонтальна. align-items работает именно вдоль неё. stretch (значение по умолчанию, уже упоминалось в уроке про то, что такое Flexbox) растягивает элементы на всю поперечную ось, но только если у элемента явно не задана своя высота. flex-start и flex-end прижимают элементы к одному краю поперечной оси, сохраняя их собственную высоту, center - выравнивает по центру поперечной оси. Пятое значение, baseline, устроено иначе - о нём отдельно в следующем разделе.
.container { display: flex; align-items: flex-start; } - элементы разной высоты выровняются по верхнему краю, каждый сохранит свою высоту.
.item { align-items: center; } на отдельном элементе - align-items, как и остальные свойства контейнера, работает только будучи заданным на самом контейнере.
baseline - выравнивание по базовой линии текста
baseline выравнивает элементы не по верхнему краю и не по центру, а по невидимой линии, на которой "стоят" буквы текста - базовой линии (baseline). Это особенно заметно, когда элементы содержат текст разного размера: у элемента с крупным шрифтом строка выше базовой линии займёт больше места, чем у элемента с мелким шрифтом, поэтому его верхний край окажется ВЫШЕ, чем у соседнего элемента с мелким текстом - хотя сам текст в обоих элементах будет казаться "стоящим на одной линии". Это удобно для строк вроде цены с крупной цифрой и мелкой припиской "руб." рядом - baseline совместит их так, как выглядело бы обычное предложение.
.container { display: flex; align-items: baseline; } с элементами разного размера шрифта внутри - текст во всех элементах окажется на одной видимой линии.
.container { display: flex; align-items: flex-start; }, ожидая эффект "текст на одной линии" для элементов с разным размером шрифта - flex-start выравнивает по верхнему краю блока, а не по тексту, и линии текста разъедутся.
align-items и align-self: как переопределить выравнивание одного элемента
align-items задаётся на контейнере и действует сразу на все элементы внутри. Если нужно, чтобы ОДИН конкретный элемент вёл себя иначе, чем остальные, для этого есть отдельное свойство align-self - оно задаётся прямо на самом элементе и принимает те же значения (stretch, flex-start, flex-end, center, baseline), но переопределяет align-items контейнера только для этого элемента, не трогая соседей. Отдельно стоит не путать align-items с похожим по названию align-content: align-content выравнивает уже не отдельные элементы, а целые СТРОКИ элементов, и работает только тогда, когда flex-wrap: wrap создаёт несколько строк - в обычном однострочном контейнере align-content ни на что не влияет.
.item:last-child { align-self: flex-end; } - именно последний элемент прижмётся к низу контейнера, остальные останутся там, где их разместил align-items.
.container { align-content: center; }, ожидая эффект от одного элемента - align-content управляет строками при переносе, а не отдельными элементами; для одного элемента нужен align-self.
Частые ошибки новичков
| Ошибка | Что происходит | Как исправить |
|---|---|---|
| Не понимают, почему элементы растягиваются на всю высоту сами по себе | Кажется багом, хотя это stretch по умолчанию | Задать элементу явную высоту или указать другое значение align-items |
| Путают align-items с align-content | Пишут align-content, ожидая эффект для отдельных элементов в одну строку - ничего не меняется | align-items - для элементов в одной строке; align-content - только для нескольких строк при flex-wrap: wrap |
| Ожидают, что baseline выровняет элементы по верхнему краю, как flex-start | Элементы с разным размером шрифта визуально "разъезжаются" по верхнему краю | Помнить: baseline выравнивает текст, а не сам блок - верхние края у элементов разной высоты будут разными |
| Пишут align-self на контейнере вместо align-items | Свойство не действует - align-self предназначено для отдельного элемента | На контейнере - align-items, на конкретном элементе, который нужно выделить, - align-self |
Шпаргалка
| Что нужно | Как сделать |
|---|---|
| Растянуть на всю высоту (по умолчанию) | align-items: stretch; |
| Прижать к началу поперечной оси | align-items: flex-start; |
| Прижать к концу поперечной оси | align-items: flex-end; |
| Выровнять по центру поперечной оси | align-items: center; |
| Выровнять текст разного размера по одной линии | align-items: baseline; |
| Переопределить выравнивание для одного элемента | align-self: значение; на этом элементе |
Коротко: отвечаем на вопросы
Почему элементы растягиваются на всю высоту контейнера сами по себе?
Это align-items: stretch - значение по умолчанию для flex-контейнеров. Если у элемента явно не задана своя высота, он растянется на всю поперечную ось контейнера. Чтобы этого избежать, нужно либо задать элементу явную высоту, либо указать другое значение align-items, например flex-start.
Чем align-items отличается от align-content?
align-items выравнивает элементы внутри одной строки - то есть работает всегда, даже если строка одна. align-content выравнивает уже сами строки относительно друг друга, но только когда flex-wrap: wrap создаёт несколько строк. В обычном однострочном контейнере align-content ни на что не влияет.