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

Display: block, inline, flex

Ты хочешь поставить несколько кнопок в ряд, но они почему-то стоят столбиком. Или пытаешься задать ширину ссылке, но ничего не меняется. Это поведение определяет свойство display — одно из самых фундаментальных в CSS.

display: block

Блочный элемент занимает всю доступную ширину и начинается с новой строки.

display: block;

Блочные по умолчанию: div, p, h1–h6, ul, ol, li, header, section, article.

  • Ширина = 100% родителя (если не задать явно)
  • Принимает width, height, margin, padding со всех сторон
  • Следующий элемент всегда начинается с новой строки
  • display: inline

    Строчный элемент — ведёт себя как слово в тексте: встаёт в поток строки.

    display: inline;

    Строчные по умолчанию: span, a, strong, em, img, button, input.

  • Ширина и высота определяются содержимым
  • width и height не работают
  • Вертикальный margin не работает, горизонтальный — работает
  • Несколько inline-элементов стоят в одну строку
  • display: inline-block

    Лучшее из двух миров: стоит в строке как inline, но принимает все свойства блочного.

    display: inline-block;
  • Можно задать width, height, вертикальный margin
  • Несколько элементов стоят в ряд
  • Между ними есть небольшой пробел (от пробелов в HTML-коде)
  • Применяется для: кнопок в ряд, плашек-тегов, значков.

    display: none

    Полностью скрывает элемент — он не занимает место и не отрисовывается.

    .hidden { display: none; }

    Применяется для: скрыть меню до клика, убрать элемент на мобильных, переключение вкладок.

    visibility: hidden — похожее, но другое

    .invisible { visibility: hidden; }

    Элемент скрыт, но место сохраняется. Сосед не двигается.

    display: none      → элемент исчезает, место освобождается
    visibility: hidden → элемент невидим, но место занято

    display: flex — превью

    Превращает элемент в flex-контейнер. Дети автоматически встают в ряд и их легко выравнивать.

    .nav {
      display: flex;
      gap: 16px;
      align-items: center;
    }

    Flex — основа современных layouts. Подробно разберём в следующих уроках.

    Изменение display по умолчанию

    /* Сделать ссылки блочными (для вертикального меню) */
    nav a { display: block; padding: 12px 16px; }
    
    /* Сделать li в ряд (горизонтальное меню) */
    nav li { display: inline-block; }
    
    /* Скрыть кнопку на мобильных */
    @media (max-width: 768px) {
      .desktop-only { display: none; }
    }

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

    Ошибка 1: Задать width inline-элементу

    span { width: 200px; }   /* Не сработает — span это inline */
    span { display: inline-block; width: 200px; }  /* Работает */

    Ошибка 2: Перепутать display:none и visibility:hidden

    /* Хочешь скрыть, но не освобождать место (анимации, placeholder) */
    .loading-spinner { visibility: hidden; }  /* Правильно */
    
    /* Хочешь убрать элемент полностью */
    .modal { display: none; }  /* Правильно */

    Ошибка 3: Лишние пробелы между inline-block элементами

    <div class="tag">CSS</div>
    <div class="tag">HTML</div>
    <!-- Между тегами есть пробел в HTML → щель между элементами в браузере -->

    Решение — flexbox (там нет этой проблемы).

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

    В современном CSS inline-block почти полностью вытеснен flexbox — flex решает те же задачи лучше. Но понимать block и inline обязательно: это основа того, как браузер строит страницу. Знание того, какие элементы блочные, а какие строчные — база, без которой невозможно понять, почему вёрстка ведёт себя именно так.

    Примеры

    block, inline, inline-block — в чём разница

    // Добавляем стили
    const style = document.createElement('style')
    style.textContent = `
      .demo-block { background: #bee3f8; margin: 4px 0; padding: 8px; }
      .demo-inline { background: #fbb6ce; padding: 4px 8px; }
      .demo-inline-block { background: #c6f6d5; padding: 8px 16px; margin: 4px; }
    `
    document.head.appendChild(style)
    
    const section = document.createElement('div')
    document.body.appendChild(section)
    
    // === BLOCK ===
    const blockLabel = document.createElement('p')
    blockLabel.textContent = 'display: block — каждый занимает всю строку:'
    section.appendChild(blockLabel)
    
    ;['Блок 1', 'Блок 2', 'Блок 3'].forEach(text => {
      const div = document.createElement('div')
      div.className = 'demo-block'
      div.textContent = text
      section.appendChild(div)
    })
    
    // === INLINE ===
    const inlineLabel = document.createElement('p')
    inlineLabel.textContent = 'display: inline — все в одну строку:'
    section.appendChild(inlineLabel)
    
    ;['Тег1', 'Тег2', 'Тег3'].forEach(text => {
      const span = document.createElement('span')
      span.className = 'demo-inline'
      span.textContent = text
      // inline по умолчанию для span
      section.appendChild(span)
      section.appendChild(document.createTextNode(' '))
    })
    
    // === INLINE-BLOCK ===
    const ibLabel = document.createElement('p')
    ibLabel.style.marginTop = '12px'
    ibLabel.textContent = 'display: inline-block — в ряд, но с размерами:'
    section.appendChild(ibLabel)
    
    ;['Кнопка A', 'Кнопка B', 'Кнопка C'].forEach(text => {
      const btn = document.createElement('div')
      btn.className = 'demo-inline-block'
      btn.style.display = 'inline-block'
      btn.style.width = '100px'    // width работает у inline-block!
      btn.textContent = text
      section.appendChild(btn)
    })
    
    // === DISPLAY: NONE vs VISIBILITY: HIDDEN ===
    const gone = document.createElement('div')
    gone.textContent = 'Я скрыт через display:none'
    gone.style.display = 'none'
    gone.style.backgroundColor = '#fed7d7'
    section.appendChild(gone)
    
    const invisible = document.createElement('div')
    invisible.textContent = 'Я скрыт через visibility:hidden (место занято)'
    invisible.style.visibility = 'hidden'
    invisible.style.backgroundColor = '#fef3c7'
    invisible.style.padding = '8px'
    section.appendChild(invisible)
    
    const after = document.createElement('div')
    after.textContent = '← Я следую после скрытых блоков'
    after.style.backgroundColor = '#e0e7ff'
    after.style.padding = '8px'
    section.appendChild(after)
    
    // Читаем display
    console.log('display:none — computed display:', window.getComputedStyle(gone).display)
    // none
    console.log('visibility:hidden — computed visibility:', window.getComputedStyle(invisible).visibility)
    // hidden
    console.log('visibility:hidden — место занято (display):', window.getComputedStyle(invisible).display)
    // block (элемент есть, просто невидим)

    Display: block, inline, flex

    Ты хочешь поставить несколько кнопок в ряд, но они почему-то стоят столбиком. Или пытаешься задать ширину ссылке, но ничего не меняется. Это поведение определяет свойство display — одно из самых фундаментальных в CSS.

    display: block

    Блочный элемент занимает всю доступную ширину и начинается с новой строки.

    display: block;

    Блочные по умолчанию: div, p, h1–h6, ul, ol, li, header, section, article.

  • Ширина = 100% родителя (если не задать явно)
  • Принимает width, height, margin, padding со всех сторон
  • Следующий элемент всегда начинается с новой строки
  • display: inline

    Строчный элемент — ведёт себя как слово в тексте: встаёт в поток строки.

    display: inline;

    Строчные по умолчанию: span, a, strong, em, img, button, input.

  • Ширина и высота определяются содержимым
  • width и height не работают
  • Вертикальный margin не работает, горизонтальный — работает
  • Несколько inline-элементов стоят в одну строку
  • display: inline-block

    Лучшее из двух миров: стоит в строке как inline, но принимает все свойства блочного.

    display: inline-block;
  • Можно задать width, height, вертикальный margin
  • Несколько элементов стоят в ряд
  • Между ними есть небольшой пробел (от пробелов в HTML-коде)
  • Применяется для: кнопок в ряд, плашек-тегов, значков.

    display: none

    Полностью скрывает элемент — он не занимает место и не отрисовывается.

    .hidden { display: none; }

    Применяется для: скрыть меню до клика, убрать элемент на мобильных, переключение вкладок.

    visibility: hidden — похожее, но другое

    .invisible { visibility: hidden; }

    Элемент скрыт, но место сохраняется. Сосед не двигается.

    display: none      → элемент исчезает, место освобождается
    visibility: hidden → элемент невидим, но место занято

    display: flex — превью

    Превращает элемент в flex-контейнер. Дети автоматически встают в ряд и их легко выравнивать.

    .nav {
      display: flex;
      gap: 16px;
      align-items: center;
    }

    Flex — основа современных layouts. Подробно разберём в следующих уроках.

    Изменение display по умолчанию

    /* Сделать ссылки блочными (для вертикального меню) */
    nav a { display: block; padding: 12px 16px; }
    
    /* Сделать li в ряд (горизонтальное меню) */
    nav li { display: inline-block; }
    
    /* Скрыть кнопку на мобильных */
    @media (max-width: 768px) {
      .desktop-only { display: none; }
    }

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

    Ошибка 1: Задать width inline-элементу

    span { width: 200px; }   /* Не сработает — span это inline */
    span { display: inline-block; width: 200px; }  /* Работает */

    Ошибка 2: Перепутать display:none и visibility:hidden

    /* Хочешь скрыть, но не освобождать место (анимации, placeholder) */
    .loading-spinner { visibility: hidden; }  /* Правильно */
    
    /* Хочешь убрать элемент полностью */
    .modal { display: none; }  /* Правильно */

    Ошибка 3: Лишние пробелы между inline-block элементами

    <div class="tag">CSS</div>
    <div class="tag">HTML</div>
    <!-- Между тегами есть пробел в HTML → щель между элементами в браузере -->

    Решение — flexbox (там нет этой проблемы).

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

    В современном CSS inline-block почти полностью вытеснен flexbox — flex решает те же задачи лучше. Но понимать block и inline обязательно: это основа того, как браузер строит страницу. Знание того, какие элементы блочные, а какие строчные — база, без которой невозможно понять, почему вёрстка ведёт себя именно так.

    Примеры

    block, inline, inline-block — в чём разница

    // Добавляем стили
    const style = document.createElement('style')
    style.textContent = `
      .demo-block { background: #bee3f8; margin: 4px 0; padding: 8px; }
      .demo-inline { background: #fbb6ce; padding: 4px 8px; }
      .demo-inline-block { background: #c6f6d5; padding: 8px 16px; margin: 4px; }
    `
    document.head.appendChild(style)
    
    const section = document.createElement('div')
    document.body.appendChild(section)
    
    // === BLOCK ===
    const blockLabel = document.createElement('p')
    blockLabel.textContent = 'display: block — каждый занимает всю строку:'
    section.appendChild(blockLabel)
    
    ;['Блок 1', 'Блок 2', 'Блок 3'].forEach(text => {
      const div = document.createElement('div')
      div.className = 'demo-block'
      div.textContent = text
      section.appendChild(div)
    })
    
    // === INLINE ===
    const inlineLabel = document.createElement('p')
    inlineLabel.textContent = 'display: inline — все в одну строку:'
    section.appendChild(inlineLabel)
    
    ;['Тег1', 'Тег2', 'Тег3'].forEach(text => {
      const span = document.createElement('span')
      span.className = 'demo-inline'
      span.textContent = text
      // inline по умолчанию для span
      section.appendChild(span)
      section.appendChild(document.createTextNode(' '))
    })
    
    // === INLINE-BLOCK ===
    const ibLabel = document.createElement('p')
    ibLabel.style.marginTop = '12px'
    ibLabel.textContent = 'display: inline-block — в ряд, но с размерами:'
    section.appendChild(ibLabel)
    
    ;['Кнопка A', 'Кнопка B', 'Кнопка C'].forEach(text => {
      const btn = document.createElement('div')
      btn.className = 'demo-inline-block'
      btn.style.display = 'inline-block'
      btn.style.width = '100px'    // width работает у inline-block!
      btn.textContent = text
      section.appendChild(btn)
    })
    
    // === DISPLAY: NONE vs VISIBILITY: HIDDEN ===
    const gone = document.createElement('div')
    gone.textContent = 'Я скрыт через display:none'
    gone.style.display = 'none'
    gone.style.backgroundColor = '#fed7d7'
    section.appendChild(gone)
    
    const invisible = document.createElement('div')
    invisible.textContent = 'Я скрыт через visibility:hidden (место занято)'
    invisible.style.visibility = 'hidden'
    invisible.style.backgroundColor = '#fef3c7'
    invisible.style.padding = '8px'
    section.appendChild(invisible)
    
    const after = document.createElement('div')
    after.textContent = '← Я следую после скрытых блоков'
    after.style.backgroundColor = '#e0e7ff'
    after.style.padding = '8px'
    section.appendChild(after)
    
    // Читаем display
    console.log('display:none — computed display:', window.getComputedStyle(gone).display)
    // none
    console.log('visibility:hidden — computed visibility:', window.getComputedStyle(invisible).visibility)
    // hidden
    console.log('visibility:hidden — место занято (display):', window.getComputedStyle(invisible).display)
    // block (элемент есть, просто невидим)

    Задание

    Напиши HTML-страницу с горизонтальным навигационным меню из трёх ссылок: "Главная", "Каталог", "Контакты". Используй теги <a> с display: inline-block, padding: 8px 16px, фиолетовым фоном (#7b2ff7) и белым текстом. Добавь четвёртую скрытую ссылку "Секрет" с display: none.

    Подсказка

    display: inline-block позволяет ссылкам стоять в ряд и принимать padding. display: none полностью убирает элемент — он не занимает место. Ссылка "Секрет" добавляет класс nav-secret поверх nav-link — правило с display: none перекрывает inline-block.

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