Перейти к содержанию

Каскад и наследование CSS

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

Наш HTML уже выполняет основные задачи без оформления: показывает шесть курсов, открывает оглавления и передаёт параметры учебной формы. Теперь зададим цвета и семейство шрифта. Важно не перепутать действие селектора, выбор победившего объявления и наследование. Все три участвуют в результате, но отвечают на разные вопросы: к какому элементу относится правило, какое значение выбрано и откуда оно получено.

Начнём с небольшого полного файла styles.css. В этом уроке не нужна сетка, тени или сложные сбросы. Чем меньше свойств одновременно меняется, тем легче связать наблюдаемый эффект с конкретной строкой. Последующие дополнения будут сохранять эти классы, поэтому названия из HTML не нужно переименовывать после каждого нового приёма.

Селектор выбирает элемент

Сохраните следующий CSS:

.layout-lab {
  color: #e4e4e4;
  background: #1f202a;
  font-family: system-ui, sans-serif;
}
.layout-lab a {
  color: #46d96f;
}
.layout-lab .course-card {
  background: #252631;
}
.layout-lab .course-count {
  color: #b7b9c9;
}

Ожидается тёмная страница со светлым текстом, зелёными ссылками и чуть отличающимися фонами карточек. Между записями пока может не быть удобных интервалов, а картинки способны выходить за ширину окна. Эти задачи ещё не решались. Нельзя считать любую оставшуюся неровность признаком того, что файл стилей не подключён: сначала сравните свойства, которые мы действительно задали.

Первое правило выбирает body по классу. Второе выбирает ссылки, находящиеся внутри этой страницы. Пробел означает отношение потомка, а не наличие двух классов у одного элемента. Запись .layout-lab.course-card означала бы один узел с обоими классами и не подошла бы нашим карточкам. Небольшая разница в записи меняет набор выбранных элементов ещё до каскада.

Префикс страницы ограничивает правила учебным примером. Он не делает CSS недоступным снаружи и не заменяет отдельную технологию изоляции, но уменьшает риск случайно выбрать элементы другого документа при переносе блока. Все наши учебные классы имеют собственные имена. В большой системе это соглашение помогает читать границы компонентов; сейчас оно делает опыт на каталоге достаточно ясным.

Значение от родителя

Цвет текста задан на body, однако светлыми становятся и абзацы внутри карточек. Это наследование: некоторые свойства, если их не задали на дочернем элементе иначе, получают значение от родителя. Семейство шрифта также распространяется по дереву. Фон, напротив, не нужно воспринимать как автоматически скопированное свойство каждого потомка. Через прозрачные области дочерних коробок виден фон лежащего под ними элемента.

Ссылка имеет своё правило цвета, поэтому зелёное значение на ней используется вместо унаследованного светлого. Число уроков получает сероватый цвет по собственному классу. При наследовании не складываются веса селекторов разных элементов: объявление на родителе и объявление на самой ссылке не являются одинаковыми кандидатами для цвета одного узла. Это частая причина неправильного объяснения, будто «правило на body проиграло из-за слабого селектора».

У форм семейство шрифта может оставаться браузерным, пока мы не укажем для элементов управления font: inherit. Не каждый элемент выглядит так же, как соседний абзац, после одной настройки на странице. Такой результат нужно объяснять встроенными правилами и свойствами, а не добавлять случайные глобальные объявления. В четырнадцатом уроке мы отдельно оформим поля и кнопку, сохранив их нативное поведение.

Когда подходят два правила

Добавьте временно в конец файла второе правило:

.layout-lab .course-count {
  color: #83eba0;
}

Теперь ожидается зелёное число уроков. Оба объявления относятся к одному свойству одного набора элементов, имеют одинаковый селектор и находятся в обычных авторских правилах без слоёв и важности. В этих ограниченных условиях порядок в файле разрешает равенство: позже записанное объявление выбирается. Полный порядок каскада включает происхождение, важность, слои и другие этапы, поэтому утверждение «последняя строка всегда выигрывает» неверно. Механизм описан в MDN.

Переставьте это правило выше первоначального и ожидайте возвращения серого цвета. Затем верните исходный файл перед следующим уроком. Изменение цвета не затрагивает число, текст описания и адрес ссылки: CSS задаёт представление, а данные остаются в HTML. Так можно проверить границу ответственности двух файлов, не вводя никаких обработчиков.

Если написать неизвестное свойство или недопустимое значение, браузер не обязан остановить всю таблицу стилей. Ошибочное объявление может быть отброшено, а остальные продолжат действовать. Поэтому ситуация «часть оформления есть» требует поиска конкретного объявления. Пропущенная закрывающая фигурная скобка способна затронуть более крупный фрагмент; синтаксис и выбор победителя — разные виды проблем.

Как искать причину в браузере

В инструментах разработчика выберите span.course-count. Список правил должен показывать подходящие объявления; перекрытые значения обычно помечаются отдельно. Представление вычисленных свойств показывает итоговый цвет. Сначала установите, выбран ли нужный элемент и загружен ли файл, затем ищите конкурирующие правила. Добавление !important до выяснения причины лишь создаёт ещё одного участника каскада.

Полезно сравнить источник значения с родителем. Выберите описание курса: у него нет собственного color, поэтому ожидается наследование. Выберите ссылку: на ней есть явный цвет. Выберите карточку: её фон задан отдельно. Это три конкретных наблюдения, которые раскрывают механизм лучше, чем одновременная замена всего оформления готовой библиотекой.

Чтобы отличить отсутствие объявления от явного запроса наследования, попробуйте временно записать color: inherit для ссылки. Ожидается получение цвета родителя вместо зелёного авторского значения, если новое правило выигрывает в своём контексте. Затем удалите опытное правило. Ключевое слово сообщает конкретное намерение, а не удаляет элемент из каскада.

Не называйте любое возвращение к браузерному виду «сбросом всех стилей». Разные ключевые слова CSS имеют разные действия, а библиотечный reset представляет собой обычный набор правил. Для нашей страницы достаточно небольших явных объявлений. Их проще связать с текущим результатом и отменить по одному, чем подключать неизвестный большой файл и объяснять каждое отличие его скрытым содержимым.

Иногда после сохранения CSS вид остаётся прежним из-за открытого старого файла или сохранённого ресурса браузера. Перед усилением селекторов сравните адрес документа и содержимое загруженной таблицы стилей. В папках снимков все файлы называются одинаково, но находятся в разных каталогах. Можно легко редактировать lesson-06/styles.css, наблюдая lesson-05/index.html. Это ошибка выбора состояния проекта, а не необычное правило каскада. Понятные названия вкладок и проверка пути помогают отделять такие случаи от конфликта CSS.

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

Оглавление курса