Урок · CSS
display: как элемент встаёт на страницу
Свойство display решает две вещи: как сам элемент ведёт себя среди соседей (встаёт отдельной строкой или живёт внутри текста) и по каким правилам раскладываются его дети (обычный поток, flex или grid). Значение none полностью убирает элемент со страницы.
blockначинает новую строку и растягивается на всю доступную ширину.inlineживёт внутри текста: width, height и вертикальные margin на него не действуют.inline-blockстоит в строке, но принимает размеры и отступы как блок.flexиgridменяют раскладку детей, а не самого элемента.display: noneубирает элемент из раскладки и от скринридеров.
Зачем этот урок сейчас
Почти каждая «странность» вёрстки начинается с display: ширина ссылки не меняется, отступ сверху у span не работает, justify-content ничего не делает. Во всех трёх случаях у элемента не то значение display, которое ты ожидал. Разберёшься с ним — дальше Flexbox, Grid и адаптивная вёрстка пойдут без сюрпризов.
Минимальный пример
Три элемента с тремя разными значениями. Вставь код в песочницу и сравни, как они встают.
<p class="note">Абзац — блок, занимает строку целиком.</p>
<a class="tag" href="/css/">CSS</a>
<a class="tag" href="/html/">HTML</a>.note { display: block; background: #eef2ff; }
.tag { display: inline-block; padding: 4px 10px; border-radius: 999px; background: #e0e7ff; }Абзац растянулся во всю ширину. Ссылки остались в одной строке, но приняли внутренние отступы и скругление: у inline-block это работает, у обычного inline вертикальный padding вылез бы за строку и наехал на соседей.
Основные значения display
| Значение | Сам элемент | Дети | Пример |
|---|---|---|---|
block | Новая строка, ширина на весь контейнер | Обычный поток | div, p, section |
inline | Внутри текста, ширина по содержимому | Обычный поток | span, a, strong |
inline-block | В строке, но с размерами блока | Обычный поток | кнопки-ссылки, теги |
flex | Как блок | Flexbox: ряд или колонка | меню, шапка |
inline-flex | Как inline-block | Flexbox | кнопка с иконкой |
grid | Как блок | Сетка строк и колонок | каталог карточек |
inline-grid | Как inline-block | Сетка | редко, мини-виджеты |
flow-root | Как блок | Новый контекст форматирования | родитель с float внутри |
contents | Собственной рамки нет | Дети встают на его место | обёртка внутри grid |
none | Не отображается | Не отображаются | скрытое меню |
В спецификации display описан двумя словами: внешнее поведение и внутреннее. display: flex — то же самое, что display: block flex, а inline-flex — inline flex. Двухсловная запись работает в современных браузерах, но в учебных проектах привычнее однословная.
Чем block отличается от inline
Блочный элемент начинает новую строку, принимает width, height и все четыре отступа. Если ширину не задать, он растягивается на всю ширину родителя.
Строчный элемент — часть текста. Его ширина равна ширине содержимого, а width и height игнорируются. Горизонтальные margin и padding раздвигают соседей, вертикальные — рисуются, но строку не сдвигают: фон padding наедет на строку выше.
/* не сработает: span остаётся строчным */
.price { width: 120px; margin-top: 20px; }
/* сработает */
.price { display: inline-block; width: 120px; margin-top: 20px; }Исключение — заменяемые элементы вроде img и input: они строчные, но размеры принимают, потому что у них есть собственные габариты.
Когда нужен inline-block
inline-block — компромисс: элемент стоит в строке рядом с текстом, но ведёт себя как маленький блок. Подходит для ссылок-кнопок, меток и бейджей внутри абзаца.
У inline-block есть известная ловушка: между элементами появляется зазор шириной в пробел. Это обычный пробел или перенос строки из HTML. Для ряда кнопок удобнее display: flex на родителе с gap — зазор будет точным.
flex и grid меняют детей
Значения flex и grid включают новую раскладку для прямых детей элемента. Сам контейнер при этом остаётся блоком. Поэтому justify-content или gap на обычном блоке ничего не делают: эти свойства работают только внутри flex- или grid-контейнера.
.menu { display: flex; flex-wrap: wrap; gap: 16px; }
.cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 20px; }Подробно — в уроках Flexbox и CSS Grid.
Как спрятать элемент: display, visibility, hidden, opacity
| Способ | Место в раскладке | Скринридер | Клик и Tab |
|---|---|---|---|
display: none | Исчезает | Не читает | Нет |
атрибут hidden | Исчезает | Не читает | Нет |
visibility: hidden | Остаётся пустое место | Не читает | Нет |
opacity: 0 | Остаётся | Читает | Да — ловушка |
Атрибут hidden в HTML работает как display: none, но говорит о смысле: «сейчас этот блок не нужен». Если в CSS задать элементу свой display, атрибут hidden перестанет его прятать — стили победят. Помогает правило [hidden] { display: none !important; }.
Для текста, который нужен только скринридеру (например, подпись у кнопки-иконки), display: none не подходит — используют визуально скрытый класс с clip и размером 1px.
flow-root и contents
display: flow-root создаёт новый контекст блочного форматирования. На практике это лечит две старые проблемы: родитель перестаёт «схлопываться», если внутри только float, и margin первого ребёнка перестаёт вытекать наружу через родителя.
.media { display: flow-root; } /* родитель обнимает плавающую картинку */
.media img { float: left; margin-right: 16px; }display: contents убирает рамку самого элемента: его дети ведут себя так, будто обёртки нет. Это удобно внутри grid, когда лишний div мешает детям встать в сетку. Осторожно с семантическими элементами: на кнопках, списках и таблицах display: contents в старых версиях браузеров ломал доступность.
Значения по умолчанию и семантика
У каждого HTML-элемента есть display по умолчанию из стилей браузера: div, p, h1–h6, section — block; span, a, em — inline; li — list-item; table — table. CSS меняет только внешний вид. Ссылка с display: block остаётся ссылкой, а div с display: inline не становится частью текста по смыслу.
Поэтому выбирай тег по смыслу, а display — по виду. Не делай кнопку из span с display: inline-block: у неё не будет фокуса и реакции на Enter.
Как проверить display в DevTools
Открой DevTools (F12), выбери элемент и перейди во вкладку Computed. Найди строку display: там итоговое значение после всех правил. Рядом с flex- и grid-контейнерами в панели Elements есть метка flex или grid — клик по ней рисует поверх страницы оси и ячейки.
block или inline-block
Отдельная строка, ширина на весь контейнер. Для разделов, карточек, абзацев.
Стоит в строке рядом с текстом, ширина по содержимому, но принимает размеры. Для меток и ссылок-кнопок.
Частые ошибки
- Задают
widthилиmargin-topобычномуspanиa— без inline-block или block не сработает. - Пишут
justify-contentиgapэлементу безdisplay: flexилиgrid. - Ставят flex на ребёнка, хотя раскладку детей включают на родителе.
- Прячут важный текст через
opacity: 0: его по-прежнему можно нажать и прочитать скринридером. - Задают элементу свой display и удивляются, что атрибут
hiddenбольше не скрывает его.
Доступность
display не меняет смысл элемента, поэтому сначала выбирай правильный тег. display: none и hidden прячут блок и от скринридеров — используй их для того, что сейчас действительно не нужно (закрытое меню, неактивная вкладка). Если элемент скрыт визуально, но должен читаться, применяй визуально скрытый класс. Следи, чтобы порядок в HTML совпадал с порядком на экране: flex и grid умеют переставлять блоки, а клавиатура идёт по HTML.
Поддержка браузерами
Значения block, inline, inline-block, none, flex и grid работают во всех актуальных браузерах. flow-root и contents тоже поддерживаются современными браузерами; двухсловная запись вида display: inline flex появилась позже и работает в свежих версиях. Конкретное значение сверяй на Can I use.
Практика
Сделай строку тегов под заголовком статьи: три ссылки с фоном, скруглением и внутренним отступом 4px 10px. Затем ниже — меню из четырёх ссылок в ряд с промежутком 20px, которое переносится на узком экране. Спрячь пятый пункт меню так, чтобы его не было ни видно, ни слышно скринридеру.
Показать решение
.tags a {
display: inline-block;
padding: 4px 10px;
border-radius: 999px;
background: #e0e7ff;
}
.menu {
display: flex;
flex-wrap: wrap;
gap: 20px;
}
.menu .extra {
display: none; /* или атрибут hidden в HTML */
}Частые вопросы
Почему width не работает у span?
span по умолчанию строчный (inline), а строчные элементы берут ширину по содержимому. Задай display: inline-block или block, и width начнёт работать.
Чем display: none отличается от visibility: hidden?
display: none убирает элемент вместе с его местом — соседи сдвигаются. visibility: hidden прячет элемент, но оставляет пустое место такого же размера. Оба способа скрывают элемент от скринридера.
Почему не работает justify-content?
Это свойство flex- и grid-контейнера. Проверь, что у родителя стоит display: flex или grid и что ты выравниваешь именно его прямых детей.
Что выбрать для ряда кнопок: inline-block или flex?
Flex на родителе с gap. У inline-block между кнопками появляется зазор от пробела в HTML, а выравнивание по высоте сложнее.
Меняет ли display смысл тега?
Нет. CSS влияет только на отображение. Ссылка с display: block остаётся ссылкой, а поисковик и скринридер по-прежнему видят тег, а не его стиль.