Вы не знаете CSS. Мои вопросы о CSS с ответами. Часть 2
- среда, 26 марта 2025 г. в 00:00:14

Хабр, привет! Я стабильно пишу здесь о CSS. Мне радостно, что моя работа вам полезна. Но хочется чего-то нового. Вызывающего споры. В общем, я к формату статей в виде вопрос-ответ. Вопросы будут те, что я спрашиваю на интервью. Так что у вас будет повод сказать: «А зачем это надо?».
При составлении вопросов я хотел проверить понимание базовых моментов, которые есть в вёрстке любого проекта. Ещё будут вопросы на знание более редких аспектов и «новинок» в CSS. В общем, я хочу вас завалить, чтобы казаться супер умным! (здесь ирония).
Пожалуйста, не воспринимайте мои вопросы серьёзно. Давайте просто весело проведём время. Плюс попробуем узнать что-то новое. Ведь у каждого вопроса будет мой ответ. И вы тоже можете оставить свой в комментариях. Я обязательно буду их читать.
Так, вы готовы? Давайте посмотрим, что я вам подготовил.
:focus-within и :has(:focus-visible)?<body>
<div class="awesome-block">
<a href="https://habr.com/">Великолепная ссылка</a>
</div>
</body>
Случай №1
.awesome-block:focus-within {
background-color: lightblue;
}
Случай №2
.awesome-block:has(:focus-visible) {
background-color: lightblue;
}
Псевдо-класс :focus-within срабатывает, когда пользователь сфокусировался на дочерний элемент. При этом неважно, каким способом. Проще говоря, псевдо-класс :focus-within сразу отслеживает состояния :focus и :focus-visible. В отличие от него псевдо-класс :has(:focus-visible) сработает только, если браузеры определили сработавшее состояние :focus-visible.
Правильный ответ: Есть. Первым псевдо-класс сработает, если у дочерних элементов сработали псевдо-класс :focus или :focus-visible. Псевдо-класс has(:focus-visible) срабатывает только, если у дочерних элементов сработал псевдо-класс :focus-visible.
:not() в первом и во втором случае?Случай №1
.awesome-block:not(:last-of-type) {
background-color: lightblue;
}
Случай №2
.awesome-block:not(:last-of-type, #unique-block) {
background-color: lightblue;
}
В качестве аргумента псевдо-класс :not() принимает список селекторов. Это означает, что мы можем передать любое количество селекторов, перечисляя их через запятую. Поэтому оба фрагмента кода корректны.
Правильный ответ: Да. Оба фрагмента кода написаны правильно.
height у элементов с классом .awesome-block будет одинаковым?<body>
<div class="awesome-container">
<div class="awesome-block">Великолепный текст</div>
<div class="awesome-block">Великолепный текст</div>
</div>
</body>
Случай №1
.awesome-container {
display: grid;
gap: 20px;
height: 300px;
}
.awesome-block {
background-color: lightblue;
}
Случай №2
.awesome-container {
display: flex;
flex-direction: column;
gap: 20px;
height: 300px;
}
.awesome-block {
background-color: lightblue;
}
В первом случае используется свойство display со значением grid для элемента с классом .awesome-container. По этой причине его дочерние элементы будут стремиться занимать всё доступное пространство по вертикали. Следовательно, они распределят его между собой равномерно.
Поскольку у родительского элемента также установлено свойство gap, то его значение нужно вычесть из значения свойства height и поделить на два. В итоге получаем, что у каждого элемента с классом .awesome-block будет установлено значение 140px.
Во втором случае для элемента с классом .awesome-container используется свойство display со значением flex. Также есть свойство flex-direction со значением column. Это означает, что основная ось флекс-контейнера является вертикальной. По ней браузеры не растягивают размер флекс-элемента. Поэтому значение свойства height будет рассчитано по высоте контента. Это явно меньше 140px.
Правильный ответ: Нет. В первом случае значение свойства height у элементов с классом .awesome-block будет больше, чем во втором.
.awesome-text не располагаются в строку?<body>
<span class="awesome-text">Великолепный текст</span>
<span class="awesome-text">Великолепный текст</span>
</body>
body {
display: grid;
}
На позиционирование элементов влияет свойство display. Самый главный нюанс заключается в том, что важно не только значение, установленное у самих элементов, но и значение, установленное у родительского элемента. Если у родителя используется значения block, flow или flow-root, то элементы со значением inline будут располагаться в строку.
В нашем же примере установлено значение grid. При этом значении дочерние элементы располагаются в столбец. Неважно, какое значение для свойства display используется у самих элементов.
Правильный ответ: У родительского элемента <body> вместо стандартного значения block установлено значение grid для свойства display. По этой причине браузеры перестают отображать дочерние элементы с классом .awesome-text в строку. Теперь они будут отображены в столбец.
<body>
<div class="awesome-block"></div>
</body>
Случай №1
.awesome-block::before {
content: "";
background-color: lightblue;
position: relative;
width: 1rem;
height: 1rem;
}
Случай №2
.awesome-block::before {
content: "";
background-color: lightblue;
position: absolute;
width: 1rem;
height: 1rem;
}
Значение relative и absolute по-разному влияют на значение свойства display. Первое никак его не затрагивает, а второе меняет на блочную альтернативу. Рассмотрим, как это происходит в нашем вопросе.
По умолчанию у псевдо-элемента ::before используется значение inline для свойства display. В первом случае используется значение relative. Оно не изменяет значение свойства display, поэтому браузеры не могут установить значение 1rem для свойств width и height. Следовательно, мы не увидим элемент.
Во втором случае используется значение absolute. Оно меняет значение inline на блочную альтернативу, т.е. значение block. При этом значении браузеры могут установить значение 1rem для свойств width и height. В итоге мы видим квадрат.
Правильный ответ: Ложь. В первом случае мы ничего не увидим, а во втором будет отображён квадрат.
::before находиться на одной и той же позиции при прокрутке страницы?.awesome-block {
transform: translate3d(0, 0, 0);
}
.awesome-block::before {
content: "";
background-color: lightblue;
position: fixed;
width: 1rem;
height: 1rem;
}
Для вычисления позиции и размеров элементов с установленным свойством position браузеры используют родительскую область. В стандарте её называют containing block. У элементов с position: fixed такой областью обычно является вьюпорт. По этой причине элемент становится зафиксированным при прокрутке страницы.
Только мы можем изменить это поведение. В CSS есть ряд свойств, которые меняют область containing block. Например, свойство transform. Если оно будет объявлено с любым значением, кроме none, то этот элемент будет являться областью containing block. По этой причине в нашем примере элемент перестаёт быть зафиксированным.
Правильный ответ: Нет, потому что используется свойства transform для родительского элемента.
padding?:root {
--padding-main: 10px;
--padding-extra: 15px;
--padding: var(--padding-main) var(--padding-extra);
}
.awesome-block {
--padding-main: 20px;
padding: var(--padding);
}
В интернете пользовательские CSS свойства называют CSS переменными. Такое название они получили по аналогии с языками программирования. Но есть один важный момент. Пользовательские CSS свойства не сохраняют значение, а только передают его. По этой причине мы не можем изменять уже переданное значение.
В нашем примере для пользовательского свойства --padding будут переданы значения 10px и 15px в правиле с селектором :root. Их уже дальше в коде изменить не получится. В итоге браузеры понимают, что в пользовательском свойстве --padding используется значение 10px 15px и передают его дальше до строки padding: var(--padding). Потом уже заменяют функцию var() на значение. Таким образом мы получаем свойство padding со значением 10px 15px.
:root {
--padding-main: 10px;
--padding-extra: 15px;
--padding: var(--padding-main) var(--padding-extra);
}
.awesome-block {
--padding-main: 20px;
padding: var(--padding); /* после замены пользовательского свойства здесь будет padding: 10px 15px */
}
Правильный ответ: Для свойства padding будет установлено значение 10px 15px.
Случай №1
@media (min-width: 1201px) {
body {
background-color: lightblue;
}
}
Случай №2
@media (width > 1201px) {
body {
background-color: lightblue;
}
}
При объявлении медиа-функции min-width разработчик указывает значение, которое включается в диапазон. При использовании знака > значение не включается. По этой причине в первом случае на ширине вьюпорта 1201px браузеры применят стили, а во втором случае нет.
Правильный ответ: Ложь. Результат будет отличаться на ширине вьюпорта 1201px.
scrollbar-gutter?Свойство scrollbar-gutter управляет пространством, выделяемым под полосу прокрутки. Оно будет полезно при реализации элементов интерфейса, которые влияют на отображение полосы прокрутки. Например, модальные окна затрагивают полосу прокрутки окна браузера. В результате может произойти смещение контента. В этом случае свойство scrollbar-gutter позволяет избежать этого.
Правильный ответ: Свойство будет полезным в задачах, где может появиться или исчезнуть полоса прокрутки. Оно поможет избежать нежелательного смещения контента.
В этой статье мы рассмотрели вопросы, касающиеся следующих аспектов:
:focus-within и :has(:focus-visible);:not();height внутри элемента с установленным свойством display со значениями flex и grid;display;display, если к элементу объявить свойство position со значением relative и absolute;transform влияет на работу свойства position со значением fixed;scrollbar-gutter.Другие статьи из серии можно найти по тегу «sm909_questions».
Спасибо за чтение!
P.S. Помогаю больше узнать про CSS в своём ТГ-канале CSS isn't magic. Присоединяйтесь. Ссылка в профиле.
Telegram-канал со скидками, розыгрышами призов и новостями IT 💻
