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

Источник: «CSS inheritance»
Наследование в CSS — это действительно суперспособность, и именно оно превращает разработку в Интернете в удовольствие, если вы принимаете его. В этой небольшой статье я собираюсь обратить вас в супер фанатов.

Как и в случае с каскадом и специфичностью, разработчики почему-то относятся к наследованию с опаской. Но в этом нет необходимости, потому что наследование на самом деле довольно простое. Возможно, это также мой любимый аспект CSS. Сейчас объясню, почему.

Допустим, есть такой CSS:

body {
color: DarkSlateBlue;
}

Наряду с другими свойствами, color наследуется, а это значит, что каждый фрагмент текста на странице — если не задан конкретный color — станет DarkSlateBlue.

Давайте рассмотрим это подробнее и добавим немного HTML.

<article>
<h1>I am a heading</h1>
<p>I am a paragraph.</p>
<h2>Subscribe</h2>
<form>
<label for="email">Email address</label>
<input type="email" id="email" placeholder="hello@test.com">
<button>Submit</button>
</form>
</article>

See the Pen

Если посмотреть демо, то заголовки, параграф и метка отображают текст цвета DarkSlateBlue, но поле ввода (как placeholder, так и value) и кнопка по-прежнему используют цвет текста по умолчанию. Это происходит потому, что им назначены определённые цвета. Что можно увидеть в Инструментах разработчика:

button {
color: buttontext;
}

input {
color: fieldtext;
}

Это системные цвета, используемые в таблице стилей пользовательского агента (user agent) — стилях по умолчанию, применяемых браузером. Поскольку к этим элементам применяется значение color, они не наследуют цвет от body, как другие элементы на странице.

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

Это ключевое слово удобно. Не все свойства CSS наследуются, хотя многие из них наследуются. Можно использовать ключевое слово inherit, чтобы наследовать ненаследуемые свойства.

article {
display: flex;
}

h1 {
display: inherit;
}

В данном фрагменте <h1> получит вычисленное значение display: flex.

Вернёмся к нашему маленькому фрагменту HTML. Давайте сделаем так, чтобы элемент input и button наследовали цвет DarkSlateBlue. Цвет является наследуемым, но можно использовать ключевое слово inherit, чтобы заставить элемент наследовать эти свойства вместо стилей по умолчанию, назначенных таблицей стилей пользовательского агента.

input, button {
color: inherit;
}

See the Pen

Легко и просто, верно? Давайте продвинемся немного дальше и используем другое наследуемое свойство: font. Сначала установим значение font для body:

body {
color: DarkSlateBlue;
font-family: Tahoma;
font-size: 2rem;
}

Магия наследования означает, что все текстовые элементы снова унаследовали font-family, и весь текст стал больше.

See the Pen

Причина, по которой текстовые элементы, такие как заголовки, имеют больший размер, без дополнительного изменения размера, заключается в том, что стили пользовательского агента определяют их размер с помощью единиц em, представляющих собой отношение вычисленного font-size их родителя. Например, вот стиль размера шрифта h1 в стиле пользовательского агента в Chromium:

h1 {
font-size: 1.5em;
}

Поскольку мы установили font-size для body равным 2rem, браузер рассчитал его как 24px. font-size для h1 равен 1,5em, то есть 24 * 1,5: 36px.

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

Это правило placeholder в таблице стилей пользовательского агента Chromium.

::-webkit-input-placeholder {
-webkit-text-security: none;
color: darkGray;
pointer-events: none !important;
}

Значение color установлено в darkGray, поэтому даже если input наследует цвет, это не повлияет на placeholder, поскольку ему назначен более специфический стиль. Но ничего страшного, ведь всё, что нужно сделать, это использовать более кросс-браузерный селектор:

::placeholder {
color: inherit;
}

See the Pen

Управление наследованием

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

Пишите более специфичные стили

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

a {
color: red; /* Очень легко переопределяет стиль пользовательского агента */
}

Именно так можно решить вышеописанные проблемы, и, вероятно, это путь наименьшего сопротивления при создании CSS.

Используйте ключевые слова

Давайте рассмотрим ключевые слова revert, initial и unset.

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

.my-element {
color: revert;
}

Ключевое слово revert установит свойство в значение таблицы стилей пользовательского агента — он же стиль браузера по умолчанию. Итак, если бы .my-element был <button>, цвет был бы установлен обратно в buttontext, как говорилось ранее.

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

.my-element {
color: unset;
}

Ключевое слово unset может запутать. Если свойство, которому присваивается unset, является наследуемым, то фактически происходит следующее:

.my-element {
color: inherit;
}

Если это не наследуемое свойство, то значение свойства будет таким же, как и у следующего ключевого слова — initial.

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

.my-element {
color: initial;
}

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

Подведение итогов

Видите, наследование — это совсем не страшно, правда? Оно фантастически мощное, и если его принять, то можно писать меньше CSS. Кроме того, у вас будет более удобная кодовая база, а пользователи получат лучший опыт в целом. Магия.

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

Дополнительные материалы

Предыдущая Статья

Поддомены для пользователей в Laravel

Следующая Статья

CSS однострочники для улучшения (почти) любого проекта