← HTML & CSS/Flexbox: управление строкой#24 из 383← ПредыдущийСледующий →+20 XP
Полезно по теме:Гайд: старт в frontendПрактика: DOM и событияТермин: DOMМаршрут: старт с нуля

Flexbox: управление строкой

Шапка сайта с логотипом слева и кнопкой справа. Карточки товаров в ряд с равными отступами. Кнопка с иконкой и текстом по центру. Всё это решается одним инструментом — Flexbox. До его появления такие задачи требовали хаков с float или inline-block. Сегодня flexbox — стандарт вёрстки.

Flex-контейнер и flex-элементы

Flexbox работает на двух уровнях:

  • Flex-контейнер — родитель с display: flex
  • Flex-элементы — прямые дети контейнера
  • .nav {
      display: flex;  /* Всё — контейнер flex, дети стали flex-элементами */
    }

    flex-direction — направление оси

    flex-direction: row;           /* По умолчанию — горизонтально → */
    flex-direction: row-reverse;   /* Горизонтально ← */
    flex-direction: column;        /* Вертикально ↓ */
    flex-direction: column-reverse; /* Вертикально ↑ */

    Main axis (главная ось) — направление flex-direction.

    Cross axis (поперечная ось) — перпендикулярна main axis.

    justify-content — выравнивание по главной оси

    justify-content: flex-start;    /* По умолчанию — к началу оси */
    justify-content: flex-end;      /* К концу оси */
    justify-content: center;        /* По центру */
    justify-content: space-between; /* Первый у начала, последний у конца, остальные равномерно */
    justify-content: space-around;  /* Равные отступы с обеих сторон каждого элемента */
    justify-content: space-evenly;  /* Абсолютно равные промежутки */

    Пример из жизни: шапка сайта — логотип слева, меню справа:

    .header {
      display: flex;
      justify-content: space-between;
      align-items: center;
    }

    align-items — выравнивание по поперечной оси

    align-items: stretch;     /* По умолчанию — растянуть до высоты контейнера */
    align-items: flex-start;  /* К началу поперечной оси (верху при row) */
    align-items: flex-end;    /* К концу поперечной оси (низу при row) */
    align-items: center;      /* По центру поперечной оси */
    align-items: baseline;    /* По базовой линии текста */

    Вертикальное центрирование — мечта вёрстки до flexbox, теперь две строки:

    .centered {
      display: flex;
      justify-content: center;
      align-items: center;
    }

    flex-wrap — перенос элементов

    flex-wrap: nowrap;   /* По умолчанию — всё в одну строку, сжимается */
    flex-wrap: wrap;     /* Переносит на новую строку, когда не помещается */
    flex-wrap: wrap-reverse; /* Перенос в обратном направлении */

    gap — промежутки между элементами

    gap: 16px;          /* Одинаковый промежуток во всех направлениях */
    gap: 8px 16px;      /* Строки: 8px, столбцы: 16px */
    row-gap: 8px;       /* Только между строками */
    column-gap: 16px;   /* Только между столбцами */

    gap — современная замена margin на дочерних элементах. Намного удобнее.

    flex-grow, flex-shrink, flex-basis

    Управляют тем, как элементы растут и сжимаются:

    /* flex-grow: насколько элемент растёт относительно других */
    .sidebar { flex-grow: 1; }    /* Занимает 1 часть свободного места */
    .main    { flex-grow: 3; }    /* Занимает 3 части свободного места */
    
    /* flex-basis: начальный размер элемента */
    .col { flex-basis: 200px; }   /* Начинает с 200px, потом растёт/сжимается */
    
    /* flex-shrink: насколько сжимается (по умолчанию 1) */
    .logo { flex-shrink: 0; }     /* Не сжимается при нехватке места */
    
    /* Сокращённая запись flex: grow shrink basis */
    .main { flex: 1 1 auto; }   /* Растёт, сжимается, auto-размер */
    .main { flex: 1; }          /* = flex: 1 1 0 */

    Типичные ошибки

    Ошибка 1: Применять flex-свойства к контейнеру вместо детей

    /* flex-grow/shrink/basis работают на детях, не на контейнере */
    .container { flex-grow: 1; }  /* Нет смысла, если .container не flex-item */
    .container > .child { flex-grow: 1; }  /* Правильно */

    Ошибка 2: Забыть display: flex у родителя

    .parent { }   /* Не flex! justify-content и align-items не работают */
    .child { align-items: center; }  /* Это тоже не поможет — это свойство родителя */
    
    /* Правильно */
    .parent { display: flex; align-items: center; }

    В реальных проектах

    Flexbox — главный инструмент для строк компонентов: навигация, карточки в ряд, форма с лейблом и инпутом, кнопка с иконкой. Когда нужна двумерная сетка (строки И столбцы одновременно) — переходи на CSS Grid. Разделение: Flex = строки/столбцы отдельно, Grid = сетка.

    Примеры

    Flexbox навигация и карточки с justify-content и align-items

    const style = document.createElement('style')
    style.textContent = `
      * { box-sizing: border-box; }
      body { font-family: Arial, sans-serif; padding: 16px; }
    `
    document.head.appendChild(style)
    
    // === Шапка с flex: space-between ===
    const header = document.createElement('header')
    header.style.display = 'flex'
    header.style.justifyContent = 'space-between'
    header.style.alignItems = 'center'
    header.style.padding = '12px 24px'
    header.style.backgroundColor = '#1a202c'
    header.style.borderRadius = '8px'
    header.style.marginBottom = '16px'
    document.body.appendChild(header)
    
    const logo = document.createElement('span')
    logo.textContent = 'RoadToJS'
    logo.style.color = 'white'
    logo.style.fontWeight = '700'
    logo.style.fontSize = '18px'
    header.appendChild(logo)
    
    const nav = document.createElement('nav')
    nav.style.display = 'flex'
    nav.style.gap = '16px'
    ;['Уроки', 'Профиль', 'Выйти'].forEach(text => {
      const a = document.createElement('a')
      a.textContent = text
      a.style.color = '#a0aec0'
      a.style.textDecoration = 'none'
      a.style.cursor = 'pointer'
      nav.appendChild(a)
    })
    header.appendChild(nav)
    
    // === Карточки с flex и gap ===
    const grid = document.createElement('div')
    grid.style.display = 'flex'
    grid.style.gap = '12px'
    grid.style.flexWrap = 'wrap'
    document.body.appendChild(grid)
    
    const courses = ['HTML', 'CSS', 'JavaScript', 'React']
    courses.forEach(course => {
      const card = document.createElement('div')
      card.style.flex = '1 1 120px'   // grow shrink basis
      card.style.padding = '16px'
      card.style.backgroundColor = '#ebf4ff'
      card.style.borderRadius = '8px'
      card.style.textAlign = 'center'
      card.style.fontWeight = '600'
      card.textContent = course
      grid.appendChild(card)
    })
    
    // === Кнопка с иконкой по центру ===
    const btn = document.createElement('button')
    btn.style.display = 'flex'
    btn.style.alignItems = 'center'
    btn.style.gap = '8px'
    btn.style.padding = '10px 20px'
    btn.style.backgroundColor = '#7b2ff7'
    btn.style.color = 'white'
    btn.style.border = 'none'
    btn.style.borderRadius = '6px'
    btn.style.cursor = 'pointer'
    btn.style.marginTop = '16px'
    btn.innerHTML = '▶ Начать обучение'
    document.body.appendChild(btn)
    
    // Читаем стили
    const headerStyle = window.getComputedStyle(header)
    console.log('Хедер display:', headerStyle.display)           // flex
    console.log('Хедер justify-content:', headerStyle.justifyContent)  // space-between
    console.log('Хедер align-items:', headerStyle.alignItems)    // center
    
    const gridStyle = window.getComputedStyle(grid)
    console.log('Карточки display:', gridStyle.display)          // flex
    console.log('Карточки gap:', gridStyle.gap)                  // 12px
    console.log('Карточки flex-wrap:', gridStyle.flexWrap)       // wrap

    Flexbox: управление строкой

    Шапка сайта с логотипом слева и кнопкой справа. Карточки товаров в ряд с равными отступами. Кнопка с иконкой и текстом по центру. Всё это решается одним инструментом — Flexbox. До его появления такие задачи требовали хаков с float или inline-block. Сегодня flexbox — стандарт вёрстки.

    Flex-контейнер и flex-элементы

    Flexbox работает на двух уровнях:

  • Flex-контейнер — родитель с display: flex
  • Flex-элементы — прямые дети контейнера
  • .nav {
      display: flex;  /* Всё — контейнер flex, дети стали flex-элементами */
    }

    flex-direction — направление оси

    flex-direction: row;           /* По умолчанию — горизонтально → */
    flex-direction: row-reverse;   /* Горизонтально ← */
    flex-direction: column;        /* Вертикально ↓ */
    flex-direction: column-reverse; /* Вертикально ↑ */

    Main axis (главная ось) — направление flex-direction.

    Cross axis (поперечная ось) — перпендикулярна main axis.

    justify-content — выравнивание по главной оси

    justify-content: flex-start;    /* По умолчанию — к началу оси */
    justify-content: flex-end;      /* К концу оси */
    justify-content: center;        /* По центру */
    justify-content: space-between; /* Первый у начала, последний у конца, остальные равномерно */
    justify-content: space-around;  /* Равные отступы с обеих сторон каждого элемента */
    justify-content: space-evenly;  /* Абсолютно равные промежутки */

    Пример из жизни: шапка сайта — логотип слева, меню справа:

    .header {
      display: flex;
      justify-content: space-between;
      align-items: center;
    }

    align-items — выравнивание по поперечной оси

    align-items: stretch;     /* По умолчанию — растянуть до высоты контейнера */
    align-items: flex-start;  /* К началу поперечной оси (верху при row) */
    align-items: flex-end;    /* К концу поперечной оси (низу при row) */
    align-items: center;      /* По центру поперечной оси */
    align-items: baseline;    /* По базовой линии текста */

    Вертикальное центрирование — мечта вёрстки до flexbox, теперь две строки:

    .centered {
      display: flex;
      justify-content: center;
      align-items: center;
    }

    flex-wrap — перенос элементов

    flex-wrap: nowrap;   /* По умолчанию — всё в одну строку, сжимается */
    flex-wrap: wrap;     /* Переносит на новую строку, когда не помещается */
    flex-wrap: wrap-reverse; /* Перенос в обратном направлении */

    gap — промежутки между элементами

    gap: 16px;          /* Одинаковый промежуток во всех направлениях */
    gap: 8px 16px;      /* Строки: 8px, столбцы: 16px */
    row-gap: 8px;       /* Только между строками */
    column-gap: 16px;   /* Только между столбцами */

    gap — современная замена margin на дочерних элементах. Намного удобнее.

    flex-grow, flex-shrink, flex-basis

    Управляют тем, как элементы растут и сжимаются:

    /* flex-grow: насколько элемент растёт относительно других */
    .sidebar { flex-grow: 1; }    /* Занимает 1 часть свободного места */
    .main    { flex-grow: 3; }    /* Занимает 3 части свободного места */
    
    /* flex-basis: начальный размер элемента */
    .col { flex-basis: 200px; }   /* Начинает с 200px, потом растёт/сжимается */
    
    /* flex-shrink: насколько сжимается (по умолчанию 1) */
    .logo { flex-shrink: 0; }     /* Не сжимается при нехватке места */
    
    /* Сокращённая запись flex: grow shrink basis */
    .main { flex: 1 1 auto; }   /* Растёт, сжимается, auto-размер */
    .main { flex: 1; }          /* = flex: 1 1 0 */

    Типичные ошибки

    Ошибка 1: Применять flex-свойства к контейнеру вместо детей

    /* flex-grow/shrink/basis работают на детях, не на контейнере */
    .container { flex-grow: 1; }  /* Нет смысла, если .container не flex-item */
    .container > .child { flex-grow: 1; }  /* Правильно */

    Ошибка 2: Забыть display: flex у родителя

    .parent { }   /* Не flex! justify-content и align-items не работают */
    .child { align-items: center; }  /* Это тоже не поможет — это свойство родителя */
    
    /* Правильно */
    .parent { display: flex; align-items: center; }

    В реальных проектах

    Flexbox — главный инструмент для строк компонентов: навигация, карточки в ряд, форма с лейблом и инпутом, кнопка с иконкой. Когда нужна двумерная сетка (строки И столбцы одновременно) — переходи на CSS Grid. Разделение: Flex = строки/столбцы отдельно, Grid = сетка.

    Примеры

    Flexbox навигация и карточки с justify-content и align-items

    const style = document.createElement('style')
    style.textContent = `
      * { box-sizing: border-box; }
      body { font-family: Arial, sans-serif; padding: 16px; }
    `
    document.head.appendChild(style)
    
    // === Шапка с flex: space-between ===
    const header = document.createElement('header')
    header.style.display = 'flex'
    header.style.justifyContent = 'space-between'
    header.style.alignItems = 'center'
    header.style.padding = '12px 24px'
    header.style.backgroundColor = '#1a202c'
    header.style.borderRadius = '8px'
    header.style.marginBottom = '16px'
    document.body.appendChild(header)
    
    const logo = document.createElement('span')
    logo.textContent = 'RoadToJS'
    logo.style.color = 'white'
    logo.style.fontWeight = '700'
    logo.style.fontSize = '18px'
    header.appendChild(logo)
    
    const nav = document.createElement('nav')
    nav.style.display = 'flex'
    nav.style.gap = '16px'
    ;['Уроки', 'Профиль', 'Выйти'].forEach(text => {
      const a = document.createElement('a')
      a.textContent = text
      a.style.color = '#a0aec0'
      a.style.textDecoration = 'none'
      a.style.cursor = 'pointer'
      nav.appendChild(a)
    })
    header.appendChild(nav)
    
    // === Карточки с flex и gap ===
    const grid = document.createElement('div')
    grid.style.display = 'flex'
    grid.style.gap = '12px'
    grid.style.flexWrap = 'wrap'
    document.body.appendChild(grid)
    
    const courses = ['HTML', 'CSS', 'JavaScript', 'React']
    courses.forEach(course => {
      const card = document.createElement('div')
      card.style.flex = '1 1 120px'   // grow shrink basis
      card.style.padding = '16px'
      card.style.backgroundColor = '#ebf4ff'
      card.style.borderRadius = '8px'
      card.style.textAlign = 'center'
      card.style.fontWeight = '600'
      card.textContent = course
      grid.appendChild(card)
    })
    
    // === Кнопка с иконкой по центру ===
    const btn = document.createElement('button')
    btn.style.display = 'flex'
    btn.style.alignItems = 'center'
    btn.style.gap = '8px'
    btn.style.padding = '10px 20px'
    btn.style.backgroundColor = '#7b2ff7'
    btn.style.color = 'white'
    btn.style.border = 'none'
    btn.style.borderRadius = '6px'
    btn.style.cursor = 'pointer'
    btn.style.marginTop = '16px'
    btn.innerHTML = '▶ Начать обучение'
    document.body.appendChild(btn)
    
    // Читаем стили
    const headerStyle = window.getComputedStyle(header)
    console.log('Хедер display:', headerStyle.display)           // flex
    console.log('Хедер justify-content:', headerStyle.justifyContent)  // space-between
    console.log('Хедер align-items:', headerStyle.alignItems)    // center
    
    const gridStyle = window.getComputedStyle(grid)
    console.log('Карточки display:', gridStyle.display)          // flex
    console.log('Карточки gap:', gridStyle.gap)                  // 12px
    console.log('Карточки flex-wrap:', gridStyle.flexWrap)       // wrap

    Задание

    Создай flex-контейнер с тремя карточками. Задай контейнеру `display: flex`, `justify-content: space-between`, `align-items: center` и `gap: 16px`. Каждой карточке задай `flex: 1`, `padding: 16px`, светло-синий фон и скруглённые углы.

    Подсказка

    `display: flex` активирует Flexbox. `justify-content: space-between` распределяет карточки по ширине. `align-items: center` выравнивает по вертикали. `flex: 1` у карточек означает, что каждая занимает равную долю пространства.

    Загружаем среду выполнения...
    Загружаем AI-помощника...