Урок 5 из 49 · Месяц 1. HTML5 и CSS3
Flexbox и псевдокласс :hover
Содержание урока
- Зачем нужен Flexbox
- Контейнер и элементы
- Главная и поперечная оси
- Свойства контейнера
- justify-content — выравнивание по главной оси
- align-items — выравнивание по поперечной оси
- Центрирование — классика
- gap — промежутки между элементами
- flex-wrap — перенос на новую строку
- Свойства элементов
- flex-grow, flex-shrink, flex-basis
- align-self и order
- Пример: шапка сайта
- Псевдокласс :hover
- Плавность: transition
- Эффекты при наведении
- Наведение на родителя меняет ребёнка
- Родственные псевдоклассы
- Собираем: ряд карточек
- Типичные ошибки
- Практика
- Итоги
Flexbox — это способ раскладывать элементы в ряд или в колонку, выравнивать их по центру и распределять между ними место буквально парой строк CSS. В этом уроке разберём, как работает flex-контейнер, научимся строить меню, карточки в ряд и шапку сайта, а затем оживим страницу псевдоклассом :hover, который меняет стиль при наведении мыши. В конце — практика, которую на занятии дополнит ментор.
Зачем нужен Flexbox
Вспомните прошлый урок: блочные элементы всегда идут друг под другом. А что если нужно поставить три карточки в ряд, разместить логотип слева, а меню справа, или выровнять кнопку точно по центру экрана? Раньше для этого использовали хитрые приёмы, которые легко ломались. Flexbox (Flexible Box — «гибкая коробка») решает такие задачи просто и надёжно.
Контейнер и элементы
В Flexbox всегда участвуют двое:
- flex-контейнер — родитель, которому написали
display: flex; - flex-элементы — его прямые дети.
<div class="row">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
</div>
.row {
display: flex;
}
.item {
padding: 20px;
background-color: lightblue;
border: 1px solid steelblue;
}
Одна строка display: flex — и три блока встали в ряд, а не друг под другом. Каждый занимает столько места, сколько нужно его содержимому.
Главная и поперечная оси
Flexbox мыслит не «горизонталью» и «вертикалью», а двумя осями:
- главная ось (main axis) — вдоль неё выстраиваются элементы;
- поперечная ось (cross axis) — перпендикулярна главной.
flex-direction: row (по умолчанию)
главная ось →
┌─────┬─────┬─────┐ ↓
│ 1 │ 2 │ 3 │ поперечная ось
└─────┴─────┴─────┘
Направление главной оси задаёт flex-direction:
| Значение | Главная ось |
|---|---|
row |
Слева направо (по умолчанию) |
row-reverse |
Справа налево |
column |
Сверху вниз |
column-reverse |
Снизу вверх |
Это важно, потому что следующие свойства работают вдоль осей, а не вдоль сторон экрана.
Свойства контейнера
justify-content — выравнивание по главной оси
.row {
display: flex;
justify-content: space-between;
}
| Значение | Что делает |
|---|---|
flex-start |
Прижать к началу (по умолчанию) |
flex-end |
Прижать к концу |
center |
По центру |
space-between |
Крайние — к краям, между остальными равные промежутки |
space-around |
Равные отступы вокруг каждого элемента |
space-evenly |
Совершенно равные промежутки, включая края |
align-items — выравнивание по поперечной оси
.row {
display: flex;
height: 200px;
align-items: center;
}
| Значение | Что делает |
|---|---|
stretch |
Растянуть на всю высоту контейнера (по умолчанию) |
flex-start |
Прижать к началу поперечной оси (вверх) |
flex-end |
Прижать к концу (вниз) |
center |
По центру |
baseline |
Выровнять по базовой линии текста |
Именно из-за stretch по умолчанию карточки в одном ряду получаются одинаковой высоты, даже если текста в них разное количество.
Центрирование — классика
.screen {
display: flex;
justify-content: center; /* по горизонтали */
align-items: center; /* по вертикали */
min-height: 100vh; /* на весь экран */
}
Три строки — и любой элемент внутри .screen стоит ровно посередине экрана. Это один из самых частых приёмов во frontend.
gap — промежутки между элементами
.row {
display: flex;
gap: 16px; /* одинаковый промежуток между всеми элементами */
}
.grid {
display: flex;
flex-wrap: wrap;
gap: 24px 16px; /* между рядами 24px, между колонками 16px */
}
gap удобнее, чем margin: промежуток появляется только между элементами, без лишнего отступа у крайних.
flex-wrap — перенос на новую строку
По умолчанию (nowrap) flex-элементы стараются уместиться в одну строку и сжимаются, даже если места мало. С flex-wrap: wrap они переносятся на следующую строку:
.cards {
display: flex;
flex-wrap: wrap;
gap: 20px;
}
.card {
width: 280px;
}
Если окно узкое, карточки будут ложиться в два ряда, потом в один.
Свойства элементов
flex-grow, flex-shrink, flex-basis
.sidebar { flex-basis: 250px; flex-shrink: 0; }
.content { flex-grow: 1; }
flex-basis— начальный размер элемента вдоль главной оси (какwidthдля ряда).flex-grow— какую долю свободного места забрать.1— «забери всё, что осталось». Если у двух элементов1и2, второй получит вдвое больше свободного места.flex-shrink— можно ли элементу сжиматься, если места не хватает.0— нельзя.
Обычно пишут сокращение flex:
.content { flex: 1; } /* растягивается и занимает остаток */
.col { flex: 1 1 200px; } /* grow, shrink, basis */
align-self и order
.special {
align-self: flex-end; /* выровнять только этот элемент иначе, чем остальных */
}
.first {
order: -1; /* показать первым, хотя в HTML он не первый */
}
order меняет только визуальный порядок. Для программ чтения с экрана порядок остаётся как в HTML, поэтому злоупотреблять им не стоит.
Пример: шапка сайта
<header class="header">
<a class="logo" href="#">Atlas</a>
<nav class="nav">
<a href="#">Главная</a>
<a href="#">Курсы</a>
<a href="#">Контакты</a>
</nav>
<a class="btn" href="#">Войти</a>
</header>
.header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 16px 32px;
background-color: #1a202c;
}
.logo {
font-size: 1.5rem;
font-weight: 700;
color: white;
text-decoration: none;
}
.nav {
display: flex;
gap: 24px;
}
.nav a {
color: #cbd5e0;
text-decoration: none;
}
.btn {
padding: 8px 20px;
border-radius: 8px;
background-color: #3182ce;
color: white;
text-decoration: none;
}
Разбор:
.header— flex-контейнер с тремя детьми: логотип, меню, кнопка;space-betweenприжимает логотип влево, кнопку вправо, а меню ставит посередине;align-items: centerвыравнивает всех троих по вертикали, хотя у логотипа шрифт крупнее;.nav— вложенный flex-контейнер: ссылки меню стоят в ряд с промежутком 24px.
Это нормальная практика: flex-элемент сам может быть flex-контейнером для своих детей.
Псевдокласс :hover
Псевдокласс — это состояние элемента, которое пишется через двоеточие после селектора. :hover срабатывает, когда на элемент наведён курсор мыши.
.btn {
background-color: #3182ce;
}
.btn:hover {
background-color: #2b6cb0; /* при наведении — темнее */
}
Пока мышь над кнопкой, действует второе правило; убрали мышь — стиль вернулся.
Плавность: transition
Без плавности стиль меняется резко. Свойство transition делает переход анимированным:
.btn {
background-color: #3182ce;
transition: background-color 0.2s ease;
}
.btn:hover {
background-color: #2b6cb0;
}
transition пишут в обычном состоянии, а не в :hover: тогда анимация работает и при наведении, и когда курсор уходит. Формат: какое свойство, длительность, характер движения (ease, linear, ease-in-out). Чтобы анимировать всё сразу, пишут transition: all 0.2s, но лучше перечислять конкретные свойства.
Эффекты при наведении
.card {
border: 1px solid #e2e8f0;
border-radius: 12px;
padding: 24px;
transition: transform 0.2s ease, box-shadow 0.2s ease;
}
.card:hover {
transform: translateY(-4px); /* приподнять на 4px */
box-shadow: 0 10px 20px rgb(0 0 0 / 12%); /* добавить тень */
}
.nav a:hover {
color: white;
text-decoration: underline;
}
transform: translateY(-4px)сдвигает элемент вверх, не толкая соседей;box-shadow— тень: сдвиг по X, сдвиг по Y, размытие, цвет;.nav a:hover— стиль для ссылки меню под курсором.
Наведение на родителя меняет ребёнка
.card-title {
color: #2d3748;
transition: color 0.2s;
}
.card:hover .card-title {
color: #3182ce;
}
«Когда курсор над карточкой, заголовок внутри неё становится синим». Так целая карточка реагирует на наведение, а не только текст.
Родственные псевдоклассы
| Псевдокласс | Когда срабатывает |
|---|---|
:hover |
Курсор над элементом |
:active |
В момент нажатия |
:focus |
Элемент в фокусе (клик по полю ввода, переход клавишей Tab) |
:focus-visible |
Фокус с клавиатуры — для видимой обводки |
:first-child / :last-child |
Первый / последний ребёнок у родителя |
Собираем: ряд карточек
<section class="cards">
<article class="card">
<h3 class="card-title">HTML</h3>
<p>Структура страницы</p>
</article>
<article class="card">
<h3 class="card-title">CSS</h3>
<p>Оформление и раскладка</p>
</article>
<article class="card">
<h3 class="card-title">JavaScript</h3>
<p>Поведение и интерактивность</p>
</article>
</section>
.cards {
display: flex;
flex-wrap: wrap;
gap: 24px;
padding: 32px;
}
.card {
flex: 1 1 250px;
padding: 24px;
border: 1px solid #e2e8f0;
border-radius: 12px;
background-color: white;
transition: transform 0.2s ease, box-shadow 0.2s ease;
}
.card:hover {
transform: translateY(-4px);
box-shadow: 0 10px 20px rgb(0 0 0 / 12%);
}
flex: 1 1 250px означает: «начни с 250px, растягивайся, если есть место, сжимайся, если нет». На широком экране карточки делят ряд поровну, на узком — переносятся.
Типичные ошибки
display: flexнаписан элементу, а не родителю — ничего не происходит.justify-contentиalign-itemsперепутаны после сменыflex-direction: column— помните, что оси поворачиваются вместе с направлением.align-items: centerне центрирует по вертикали — у контейнера нет высоты, центрировать не в чем.transitionнаписан только в:hover— анимация есть при наведении, но не при уходе курсора.
Подробный разбор с интерактивными примерами — MDN: Flexbox (на английском) и справочник по свойству flex.
Практика
На занятии ментор даст дополнительные задания по Flexbox и разберёт ваши решения. Для самостоятельной работы:
- Центр экрана. Поставьте блок 200×200px точно по центру окна браузера. Результат: блок посередине при любом размере окна.
- Меню. Сделайте горизонтальное меню из 5 ссылок с
gap: 20px; при наведении ссылка меняет цвет плавно за 0.2s. Результат: меню в ряд, ссылки подсвечиваются. - Шапка. Повторите шапку из урока: логотип слева, меню посередине, кнопка справа, всё выровнено по вертикали. У кнопки —
:hoverс затемнением фона. Результат: аккуратная шапка как на настоящем сайте. - Карточки. Сверстайте 6 карточек с
flex-wrap: wrap, при наведении карточка приподнимается и получает тень, а её заголовок меняет цвет. Результат: при сужении окна карточки переносятся, ховер работает плавно. - Макет с боковой панелью. Сделайте
asideфиксированной ширины 250px слева иmain, занимающий всё остальное место (flex: 1). Результат: при изменении ширины окна меняется толькоmain.
Итоги
display: flexпишется родителю; его прямые дети становятся flex-элементами.flex-directionзадаёт главную ось;justify-contentвыравнивает по ней,align-items— по поперечной.gap— промежутки между элементами,flex-wrap: wrap— перенос на новую строку.flex: 1позволяет элементу занять всё свободное место.:hoverменяет стиль при наведении,transitionв обычном состоянии делает это плавным.- Не полагайтесь только на
:hover: дублируйте стили в:focus-visible.