Pull to refresh
2886.62
RUVDS.com
VDS/VPS-хостинг. Скидка 15% по коду HABR15

Готовимся к вопросам по вёрстке на интервью Frontend-разработчика: свойство display

Level of difficultyMedium
Reading time7 min
Views12K


За свою карьеру у меня было достаточно много собеседований. Конечно, одной из основных тем вопросов была вёрстка. Немного похвалюсь. Не было вопроса, на который я не ответил.


Недавно у меня появилось желание снова проверить себя и показать сообществу свои ответы на самые популярные вопросы по вёрстке. Может же быть так, что мои ответы были неполными или некорректными. Если это так, то я научусь новому. А если всё хорошо, то они помогут другим людям в подготовке к собеседованию. Кажется, это в любом случае будет полезно.


У меня получился достаточно большой список. Он составлен на основе моего опыта, опыта моих знакомых и публично доступных собеседований. Каждый вопрос будет отдельной статьёй.


Сегодня я дам ответ на следующий вопрос: «Зачем нужно использовать свойство display


▍ Что скрыто за свойством


Согласно стандарту CSS Display Module Level 3 свойство display определяет тип отображения элемента. Для большинства случаев значение состоит из двух ключевых слов. Стоп. Как двух? Мы же всю жизнь определяли одно!


Да, мы задаём значение из одного ключевого слова, а на деле оно неявно трансформируется в два. Первая часть отвечает за внешний тип отображения, а вторая за внутренний.


Мы задаём значение block для элемента <div>, а браузеры видят его как block flow.


div {
  display: block; /* здесь display: block flow */
}

Как так происходит? В стандарте есть таблица, в которой указаны все краткие версии и соответствующие полные. Браузеры используют её для работы. Например, значения block и inline для них выглядят следующим образом:


/*
block = block flow
inline = inline flow
*/

Здесь я хочу сделать паузу. Далее я буду подробнее рассматривать ключевые слова block и inline. Обратите внимание, что это не значения block и inline, которые мы указываем. Идём дальше.


Первая часть значения влияет на отображение элемента, к которому применено свойство. Таким образом определяется внешний тип отображения. В стандарте данный тип назвали <display-outside>. Для него можно использовать ключевые слова: block, inline и run-in.


block


Если к элементу будет применено ключевое слово block, то он становится элементом block-level.


inline


При использовании ключевого слова inline создаётся inline-level элемент. Правда есть исключение. Это значение inline.


В этом случае создаётся элемент inline box. Как описано в стандарте сказано это элемент inline-level, у которого в качестве внутреннего типа отображения задано ключевое слово flow. Зачем нужно было отделить этот тип? Не знаю. Оставим это на совести авторов.


run-in


Ключевое слово run-in создаёт элемент run-in box. По сути это тот же элемент inline box, только с определёнными правилами.


Вторая часть значения определяет внутренний тип отображения, влияющий на отображение дочерних элементов. Оно называется <display-inside>. Для него используются ключевые слова flow, flow-root, flex, grid, table и ruby.


flow и flow-root


Создаётся контейнер и контекст, в котором могут существовать block-level и inline-level элементы. Его называют блочным. Разница между ними в том, что второе создаёт новый блочный контекст.


flex


Ключевое слово создаёт флекс-контейнер и контекст, в котором существуют флекс-элементы. Другими словами, это тот самый контейнер, в котором создаются две оси и другие свойства, используемые вами.


grid


При использовании гридов именно это ключевое слово создаёт грид-контейнер и контекст, в котором вы добавляете строки, столбцы, шаблоны сетки и всё остальное.


table


Специальная обёртка над блочным контейнером, создающая сетку для имитации таблицы.


ruby


Ключевое слово создаёт ruby-контейнер и контекст, внутри которого можно создать фрагмент текста, который будет аннотацией к другому фрагменту текста.


Каждый тип внешнего и внутреннего отображения влияет на отображение элементов по-своему. Это и начальное положение элементов, и установка размеров, и работа свойства margin. Об этом мы поговорим в отдельной статье. А сейчас я покажу, как вы каждый день используете рассмотренные типы и не подозреваете об этом.


▍ Влияние внешнего и внутреннего типа отображения на практике


Своё объяснение я построю на примере разметки с двумя элементами <div> и <span>, вложенными в элемент <body>.


<body>
  <div>Первый элемент с display: block</div>
  <div>Второй элемент с display: block</div>
  <span>Первый элемент с display: inline</span>
  <span>Второй элемент с display: inline</span>
</body>


В браузере элементы <div> располагаются в столбец. Сначала идёт первый, а под ним находится второй. Элементы <span> расположились в строке. Первый элемент отображён в начале строки, а второй следует за ним. Вроде всё очевидно и просто. В каждом обучающем видео и туториале рассказано о таком поведении. Что ещё добавить?


А мне есть что добавить. Как говорится в обучающих материалах, такое отображение элементов получилось, потому что они блочные и строчные. Но это не совсем так! Упускается важный нюанс. Привычное поведение возможно благодаря display: block, установленному у родителя. А если быть суперточным, потому что используется ключевое слово flow.


Опираясь на таблицу с полными значениями, браузеры понимают, что значение block состоит из двух ключевых слов block flow, а значение inlineinline flow.


body {
  display: block; /* здесь display: block flow */
}

div {
  display: block; /* здесь display: block flow */
}

span {
  display: inline; /* здесь display: inline flow */
}

Ключевое слово block мы опустим. Элемент <body> является родителем для всех других, поэтому не так важно, какой внешний тип отображения у него. А на ключевом слове flow мы остановимся.


В нашем примере оно делает элемент <body> блочным контейнером. В него вложены элементы <div> и <span>, у которых используются ключевые слова block и inline. Поняв всю эту цепочку, браузеры с чистой совестью отображают элементы <div> в столбец, а элементы <span> в строку, потому что это естественное поведение block-level и inline-level (inline box) элементов внутри блочного контейнера. Без ключевого слова flow такое поведение не получилось бы.


Если вы мне не верите, давайте проведём эксперимент. Вместо ключевого слова flow будем использовать flex для элемента <body>.


body {
  display: flex; /* здесь display: block flex */
}

Элементы выстроились в линию

Поменяв значение block на flex, мы сказали браузерам заменить блочный контейнер на флекс-контейнер. По этой причине элементы <div> и <span> перестали быть block-level и inline-level (inline box) элементами. Теперь они флекс-элементы (flex items). По этой причине они абсолютно одинаково выстроились в строку.


Думаете, что-то изменится, если использовать display: inline-flex? Попробуем.


body {
  display: inline-flex; /* здесь display: inline flex */
}

Элементы выстроились в линию

Нет, элементы отображаются так же. Всё потому что мы не изменили второе ключевое слово. Оно осталось прежним — flex. Единственные изменения случились с самим элементом <body>, поскольку мы начали использовать ключевое слово inline. Как я говорил выше, в текущем примере это не так важно.


▍ Ключевые слова contents и none


Свойство display может не только контролировать, как будет отображаться элемент. Оно дополнительно управляет тем, будет ли элемент отображён в принципе. В стандарте такое поведение называют <display-box>. Есть следующие ключевые слова:


contents


Ключевое слово скрывает элемент для своего окружения, но дочерние элементы продолжают существовать в структуре страницы, становясь на его место. При этом сохраняется стилизация элементов.


none


При этом ключевом слове элемент и все его потомки перестают отображаться.


Ключевое значение none не имеет смысла рассматривать на практике. Мы всё равно ничего не увидим, потому что всё будет скрыто. А на ключевом слове contents остановлюсь.


<body>
  <ul class="list">
    <li class="list__group"><a href="#">Ссылка 1</a></li>
    <li class="list__group"><a href="#">Ссылка 2</a></li>
    <li class="list__group"><a href="#">Ссылка 3</a></li>
  </ul>
</body>

.list {
  display: grid;
  gap: 1rem;
}

.list__group {
  display: contents;
}

После того, как применится display: contents, стили, указанные в элементе .list, будут влиять на ссылки, а не на элементы <li>. В этом заключается вся фишка ключевого слова.


▍ Значение list-item


Я рассмотрел ключевые слова, из которых строятся часто используемые значения. Осталось одно, о котором с большой вероятностью вы даже не слышали. Значение list-item.


Оно состоит (внимание!) из трёх ключевых слов! Первым идёт ключевое слово для внешнего типа отображения, вторым — для внутреннего, а третьим — ключевое слово list-item.


/*
list-type = block flow list-item
*/

Ключевое слово list-item заставляет элемент генерировать псевдоэлемент ::marker. Его содержимое указывается свойством list-style.


С теорией мы закончили. Я хочу перейти к забавному моменту. Во многих справочниках есть значение list-type. Но оно не единственное! Я случайно нашёл ещё inline list-type.


<body>
  <div class="list-item">элемент c list-item</div>
  <div class="inline-list-item">элемент c inline list-item</div>
  <div class="inline-list-item">элемент c inline list-item</div>
</body>

.list-item {
  display: list-item;
}

.inline-list-item {
  display: inline list-item;
}

Элементы с маркером выстроились в линию

В последнем абзаце раздела с описанием ключевого слова сказано, что если не указан внешний тип отображения, то присваивается ключевое слово block. Я подумал, что будет, если написать ключевое слово inline перед list-item. И вот получилось значение inline list-item. Воспринимайте это просто как забавный факт.


▍ Заключение


Отвечу кратко на вопрос «Зачем нужно использовать свойство display


Свойство display управляет отображением элемента и его потомков. Большинство значений состоит из двух ключевых слов. Первое контролирует внешний тип отображения, а второе — внутренние. Мы можем использовать ключевые слова block, inline и run-in для установки внешнего типа. Ключевые слова flow, flow-root, flex, grid, table и ruby задают внутренний тип отображения. В целом отображение элемента зависит от комбинации внутреннего типа родительского элемента и внешнего типа самого элемента.


Также есть значения contents и none, управляющие как будет скрыт элемент. При первом скрывается только элемент, к которому применено display: contents, а дочерние элементы «встают» на его место. При значении none скрывается элемент и все его потомки.


Ещё я написал вторую часть. В ней рассказал про различия между значениями свойства display.


Если вам было интересна статья и вы хотите, чтобы я продолжил эту серию, то напишите, пожалуйста, вопросы, которые сбивали вас с толку на собеседовании. Я попробую ответить на них в новой статье. Спасибо за чтение.


P.S. Помогаю подготовиться к вопросам по вёрстке на собеседовании. Пишите мне в ТГ. Ссылка в профиле.


Telegram-канал со скидками, розыгрышами призов и новостями IT 💻
Tags:
Hubs:
Total votes 55: ↑55 and ↓0+55
Comments12

Articles

Information

Website
ruvds.com
Registered
Founded
Employees
11–30 employees
Location
Россия
Representative
ruvds