Наследование

Подкаст CSS - 005: Наследование

Допустим, вы только что написали CSS-код, чтобы элементы выглядели как кнопки.

<a href="http://example.com" class="my-button">I am a button link</a>
.my-button {
  display: inline-block;
  padding: 1rem 2rem;
  text-decoration: none;
  background: pink;
  font: inherit;
  text-align: center;
}

Затем вы добавляете элемент ссылки к статье контента со значением class .my-button . Однако возникает проблема: цвет текста не соответствует ожидаемому. Как это произошло?

Некоторые свойства CSS наследуются, если для них не указано значение. В случае этой кнопки color унаследован из этого CSS:

article a {
  color: maroon;
}

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

Поток наследования

Посмотрите, как работает наследование, используя этот фрагмент HTML:

<html>
  <body>
    <article>
      <p>Lorem ipsum dolor sit amet.</p>
    </article>
  </body>
</html>

Корневой элемент ( <html> ) ничего не наследует, поскольку это первый элемент документа. Добавьте немного CSS к HTML-элементу, и он начнёт каскадно распространяться по документу.

html {
  color: lightslategray;
}

Свойство color наследуется другими элементами по умолчанию. html элемент имеет color: lightslategray , поэтому все элементы, которые могут наследовать цвет, теперь будут иметь цвет lightslategray .

body {
  font-size: 1.2em;
}
p {
  font-style: italic;
}

Курсивом будет выделен только элемент <p> , поскольку это самый глубокий вложенный элемент. Наследование осуществляется только сверху вниз, а не снизу вверх к родительским элементам.

Какие свойства наследуются по умолчанию?

Не все свойства CSS наследуются по умолчанию, но многие из них наследуются. Для справки, вот полный список свойств, наследуемых по умолчанию, взятый из справочника W3 по всем свойствам CSS:

Как работает наследование

У каждого HTML-элемента есть CSS-свойство, определённое по умолчанию с начальным значением. Начальное значение — это свойство, которое не наследуется и отображается как свойство по умолчанию, если каскад не может рассчитать значение для этого элемента.

Свойства, которые могут быть унаследованы, каскадируются сверху вниз, и дочерние элементы получают вычисленное значение, представляющее значение родительского элемента. Это означает, что если у родительского элемента установлено bold font-weight все дочерние элементы будут полужирными, если только их font-weight font-weight не имеет другого значения или таблица стилей пользовательского агента не содержит значения для этого элемента.

Как явно наследовать и контролировать наследование

Наследование может влиять на элементы неожиданным образом, и в CSS есть инструменты, помогающие в этой ситуации.

Ключевое слово inherit

С помощью ключевого слова inherit можно заставить любое свойство наследовать вычисляемое значение своего родителя. Полезный способ использования этого ключевого слова — создание исключений.

strong {
  font-weight: 900;
}

Этот фрагмент CSS устанавливает для всех элементов <strong> значение font-weight 900 вместо значения по умолчанию bold , которое было бы эквивалентно font-weight: 700 .

.my-component {
  font-weight: 500;
}

Класс .my-component вместо этого устанавливает font-weight равным 500 Чтобы элементы <strong> внутри .my-component также имели font-weight: 500 добавьте:

.my-component strong {
  font-weight: inherit;
}

Теперь элементы <strong> внутри .my-component будут иметь font-weight 500 .

Вы можете явно задать это значение, но если вы используете inherit и CSS .my-component изменится в будущем, вы можете гарантировать, что ваш <strong> будет автоматически обновляться вместе с ним.

initial ключевое слово

Наследование может вызвать проблемы с вашими элементами, а initial предоставляет вам мощную возможность сброса.

Ранее вы узнали, что у каждого свойства в CSS есть значение по умолчанию. Ключевое слово initial возвращает свойству это начальное значение по умолчанию.

aside strong {
  font-weight: initial;
}

Этот фрагмент кода удалит жирный шрифт у всех элементов <strong> внутри элемента <aside> и вместо этого придаст им обычный шрифт, который является начальным значением.

Ключевое слово unset

Свойство unset ведет себя по-разному, если свойство наследуется по умолчанию или нет. Если свойство наследуется по умолчанию, ключевое слово unset будет таким же, как inherit . Если свойство не наследуется по умолчанию, ключевое слово unset будет таким же, как initial .

Запомнить, какие CSS-свойства наследуются по умолчанию, может быть сложно, и в этом контексте unset может быть полезен. Например, color наследуется по умолчанию, а margin — нет, поэтому можно написать так:

/* Global color styles for paragraph in authored CSS */
p {
  margin-top: 2em;
  color: goldenrod;
}

/* The p needs to be reset in asides, so you can use unset */
aside p {
  margin: unset;
  color: unset;
}

Теперь margin удаляется, и color возвращается к унаследованному вычисленному значению.

Вы также можете использовать значение unset со свойством all . Возвращаясь к предыдущему примеру, что произойдёт, если глобальные стили p получат несколько дополнительных свойств? Будет применяться только правило, заданное для margin и color .

/* Global color styles for paragraph in authored CSS */
p {
    margin-top: 2em;
    color: goldenrod;
    padding: 2em;
    border: 1px solid;
}

/* Not all properties are accounted for anymore */
aside p {
    margin: unset;
    color: unset;
}

Если вы измените правило aside p на all: unset , то не имеет значения, какие глобальные стили будут применены к p в будущем, они всегда будут отменены.

aside p {
    margin: unset;
    color: unset;
    all: unset;
}

Ключевое слово revert

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

Это полезно, когда вы установили стиль, но не хотите, чтобы он применялся в некоторых случаях. В то время как inherit , initial и unset определяют, как вычисляется значение стиля, revert лишь указывает, что другие созданные вами стили не применяются.

p {
  padding: 2em;
}

aside p {
  padding: revert;
}

Этот фрагмент кода задаёт отступ элементам <p> , но когда элемент <p> находится внутри элемента <aside> , padding вообще не задаётся. Вместо этого он возвращается к пользовательскому стилю (если он задан) или базовым стилям пользовательского агента.

Ключевое слово revert-layer

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

Если вы используете стороннюю библиотеку пользовательского интерфейса, полезно импортировать её в слой и добавить любые переопределения в слой с более высоким приоритетом. Затем можно удалить переопределение с помощью revert-layer , и вместо него будут использоваться значения по умолчанию из библиотеки пользовательского интерфейса.

Если ни один из других слоев не указывает значение свойства, оно будет вести себя как revert и использовать значение из более раннего источника.

Проверьте свое понимание

Проверьте свои знания о наследовании

Какие из следующих свойств наследуются по умолчанию?

animation
Анимации не передаются детям.
font-size
🎉
color
🎉
text-align
🎉
line-height
🎉

Какое значение ведет себя как inherit , если только нечего наследовать, а затем ведет себя как initial ?

reset
недопустимое значение, попробуйте еще раз!
unset
🎉
superset
недопустимое значение, попробуйте еще раз!

Ресурсы