
Хабр, привет!
Ко мне обращаются проверить знание CSS у разработчиков. Это может быть при найме или для составления плана обучения сотрудника.
В этом году я обновил свой список вопросов. Интересно, сможете ли вы на них ответить. Сразу предупреждаю, что многие вопросы каверзные. В них есть подвох. К тому же они о последних нововведениях в CSS.
Так, вы готовы? Давайте посмотрим, что я вам подготовил.
Для какого числа элементов будет применено правило?
<body>
<div class="awesome-box">1</div>
<div class="awesome-block">2</div>
<div class="awesome-box">3</div>
<div class="awesome-block">4</div>
</body>
:nth-child(2 of .awesome-box, .awesome-block) {
outline: 0.3rem dashed lightblue;
}
Ответ
Когда мы объявляем псевдо-класс nth-child
с помощью синтаксиса of S
, мы передаём список селекторов. В спецификации его называют complex-selector-list
. Браузеры ищут HTML-элементы, основываясь на нём.
В нашем примере сначала найдутся все элементы, у которых есть атрибут class
и значения .awesome-box
и awesome-block
. Далее среди них браузеры применят правило ко второму элементу.
Правильный ответ: К элементу с цифрой два.
Чем псевдо-класс :user-valid отличается от псевдо-класса :valid?
Ответ
Псевдо-классы :valid
и :user-valid
отличаются принципом работы. Первый срабатывает всегда, если у элемента некорректное значение. Второй же будет ждать момент, когда пользователь закончит взаимодействие с элементом.
Например, если псевдо-класс user-valid
применим к текстовому полю, то он сработает после того, как пользователь покинет поле.
Правильный ответ: Псевдо-класс :user-valid
срабатывает после окончания взаимодействия пользователя с элементом формы, а псевдо-класс :valid
срабатывает после готовности документной модели.
В следующем примере правило не применится, потому что в элементе div нет элемента с атрибутом id. Правда или ложь?
<body>
<div class="awesome-block">
<span>Великолепный текст</span>
</div>
</body>
.awesome-block:has(span, #awesome-block) {
background-color: lightblue;
}
Ответ
При обработке псевдо-класса :has()
браузеры воспринимают указанные селекторы как список селекторов (complex-selector-list
). При его составлении не важно, будет ли найден HTML-элемент или нет.
В нашем примере браузеры применят правило, потому что есть селектор span
, а в HTML у элемента с классом .awesome-block
есть вложенный элемент span
.
Правильный ответ: Ложь. Правило применится.
В коде неправильно установлено значение для свойства display, поэтому псевдо-элемент ::before не будет отцентрирован по горизонтали и вертикали. Правда или ложь?
.awesome-block {
display: block flex;
min-height: 50dvh;
}
.awesome-block::before {
content: "";
width: 1rem;
height: 1rem;
margin: auto;
background-color: tomato;
}
Ответ
Свойство display
поддерживает синтаксис с двумя ключевыми словами, установленными через пробел. Первое будет обозначать, каким типом является элемент в потоке документа. В стандарте ему дали название 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
При использовании ключевого слова grid
создаётся контейнер, в котором есть строки, столбцы и сетки.
table
Специальная обёртка над блочным контейнером, создающая сетку для имитации таблицы.
ruby
Ключевое слово создаёт контейнер, внутри которого можно создать фрагмент текста, являющейся аннотацией к другому фрагменту текста.
На практике значение для свойства display
можно задать двумя способами. Оба варианта будут корректными. Например, значение flex
можно написать как flex
или block flex
.
.awesome-block {
display: flex; /* или display: block flex */
}
Разработчики привыкли к более короткой записи flex
, а браузеры видят его как block flex
.
Правильный ответ: Ложь. В коде нет ошибки. Элемент будет расположен по центру по горизонтали и вертикали.
У псевдо-элемента с классом .awesome-block будет вычислено значение inline-block. Правда или ложь?
.awesome-block {
position: fixed;
display: inline-block;
}
Ответ
При использовании свойств position
и display
нужно понимать, что значения absolute
и fixed
трансформируют значение свойства display
. Браузеры будут использовать блочные альтернативы.
В нашем примере используется значение inline-block
. Его блочной альтернативой является значение block
. Оно будет вычислено.
Правильный ответ: Ложь. Браузеры вычислят значение block
.
Каким будет расстояние между левой границей родительского элемента и его дочерним псевдо-элементом ::before?
.awesome-block {
box-sizing: border-box;
width: 50rem;
min-height: 20dvh;
padding: 20px;
border: 1px solid;
}
.awesome-block::before {
content: "";
width: 1rem;
height: 1rem;
position: absolute;
background-color: tomato;
}
Ответ
При объявлении свойства position
со значением absolute
браузеры вытаскивают элемент из обычного потока документа, но не двигают его. Он остаётся на месте, где был ранее.
В нашем примере изначально элемент был сдвинут на 20px
относительно левой границы родительского элемента. Это же значение сохранится после добавления свойства position
.
Правильный ответ: 20px
.
Координаты псевдо-элемента ::before не будут рассчитаны от вьюпорта. Правда или ложь?
.awesome-block {
width: 50%;
min-height: 20dvh;
will-change: transform;
background-color: pink;
position: absolute;
top: 3rem;
left: 3rem;
}
.awesome-block::before {
content: "";
width: 1rem;
height: 1rem;
background-color: lightblue;
position: fixed;
top: 0;
}
Ответ
При использовании свойств top
, right
, bottom
и left
для расчётов координат браузеры используют специальную область containing block
. Если мы используем свойство position
со значением fixed
, то вьюпорт будет являться такой областью.
Но есть ряд свойств, которые это изменят. Одним из них является свойство will-change
со значением transform
. По этой причине областью containing block
станет элемент, у которого установлено это свойство.
В нашем примере браузеры будут элемент с классом .awesome-block
. Относительно его границ будут рассчитаны координаты.
Правильный ответ: Правда. Координаты будут рассчитаны относительно границ элемента с классом .awesome-block
.
Какая цель у ключевого слова safe в следующем примере?
.awesome-block {
width: 20rem;
min-height: 5rem;
background-color: lightblue;
display: flex;
flex-direction: column;
align-items: safe center;
justify-content: center;
overflow: hidden;
}
Ответ
По умолчанию свойства justify-content
и align-items
не учитывает размеры родительского элемента. В результате дочерние элементы могут выйти за его пределы.
Ключевое слово safe
исправляет это поведение. Браузеры начинают учитывать размеры родительского элемента. В результате если размеры дочерних элементов будут больше родительских, то они будут прижаты к границам родителя, не выходя за его пределы.
Правильный ответ: Ключевое слово safe
заставляет браузеры контролировать размеры родительского и дочерних элементов.
Какое значение будет вычислено для свойства background-color у элемента body?
:root {
--page-background-color: purple;
background-color: tomato;
}
body {
--page-background-color: inherit;
background-color: var(--page-background-color);
min-height: 100dvh;
}
Ответ
Для правильного ответа нужно помнить, что для пользовательских свойств также работает механизм наследования. Они наследуют значение между друг другом, если у них одинаковое наименование. В нашем примере это --page-background-color
.
По этой причине браузеры наследуют значение purple
из пользовательского свойства --page-background-color
из первого правила, а потом передают его в свойство background-color
.
Правильный ответ: purple
.
Браузеры не вычислят значение 1200px для свойства width. Почему?
:root {
--page-width: 1200px;
}
body {
width: calc(var(--page-width) + var(--page-default-gap, 0));
}
Ответ
При работе с математической функцией calc()
нужно помнить, что значение 0
вызывает проблемы. Если оно используется для свойства, ожидающего значение типом length
, и указано без единиц измерения, то будет ошибка. В стандарте сказано, что значение 0
без единиц измерения не поддерживается.
По этой причине браузеры не могут сложить два операнда.
Правильный ответ: Значение не будет вычислено, потому что значение 0
без единиц измерения не поддерживается для свойств, которые ожидают значение с типом length
. В нашем примере это свойство width
.
Однако браузеры вычислят значение. Оно будет соответствовать ширине вьюпорта.
Какое значение вычислят браузеры для свойства background-color?
<body>
<div id="awesome-block" class="awesome-block">
<span>Я дочерний элемент</span>
</div>
</body>
@layer basic, components;
@layer components {
.awesome-block {
background-color: tomato;
}
}
@layer basic {
#awesome-block {
background-color: green;
}
}
Ответ
В нашем примере используются CSS-слои, поэтому специфичность селекторов будет рассчитана с учётом них. Есть правило, что последний объявленный слой с помощью правила @layer
является самым приоритетным.
У нас это слой components
. Следовательно, значение tomato
будет приоритетнее, чем значение green
из слоя basic
.
Правильный ответ: Будет вычислено значение tomato
.
Какое значение вычислят браузеры для свойств inline-size и block-size у псевдо-элемента ::before?
.awesome-block {
inline-size: 1000px;
min-block-size: 300px;
background-color: pink;
position: relative;
}
.awesome-block::before {
content: "";
inline-size: 50%;
block-size: 20%;
background-color: lightblue;
position: absolute;
}
Ответ
В нашем примере используются логические свойства inline-size
, block-size
и min-block-size
. Они являются альтернативой свойствам width
, height
и min-height
.
.awesome-block {
width: 1000px;
min-height: 300px;
background-color: pink;
position: relative;
}
.awesome-block::before {
content: "";
width: 50%;
height: 20%;
background-color: lightblue;
position: absolute;
}
Данный вид свойств реагирует на изменение направления текста. В остальном же они ведут себя как привычные свойства. Поэтому принцип расчёта значения для свойств inline-size
и block-size
такой же, как для width
и height
.
У элементов с установленным свойством position
со значением absolute
значение будет рассчитано относительно элемента с нестатическим типом позиционироавния.
В нашем примере браузеры выполнят вычисления относительно элемента с классом .awesome-block
.
Правильный ответ: Для свойства inline-size
будет вычислено значение 500px
, а для свойства block-size
— 60px
.
Заключение
Вот и все мои вопросы. Поделитесь в комментариях своими впечатлениями. Какие вопросы понравились, а какие нет. Интересно узнать ваше мнение.
Спасибо за чтение!
P. S. Помогаю больше узнать про CSS в своём ТГ-канале CSS isn't magic. Присоединяйтесь. Ссылка в профиле.
© 2025 ООО «МТ ФИНАНС»
Комментарии (6)
ShamanR
07.10.2025 09:07>К тому же они о последних нововведениях в CSS.
А подскажите, в компаниях где вас нанимают для консультаций, поддерживают какие браузеры? Если только латест хромиум, то вопросов не имею, а если нужен сафари 16, то думаю вы уже сами поняли мой немой риторический вопрос.
urvanov
07.10.2025 09:07А это реально прямо на собеседованиях кто-то должен ответить? Прямо сходу, без документации?
Kwisatz
Простите, вы это серьезно? Вам настолько делать нечего?
melnik909 Автор
Я этим 10 лет занимаюсь. Пока еще держусь