Herança

Podcast do CSS - 005: herança

Digamos que você acabou de escrever um CSS para fazer os elementos parecerem um botão.

<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;
}

Em seguida, você adiciona um elemento de link a um artigo de conteúdo com um valor class de .my-button. No entanto, há um problema, o texto não é a cor que você esperava que tivesse. Como isso aconteceu?

Algumas propriedades CSS são herdadas se você não especificar um valor para elas. No caso desse botão, ele herdou o color do CSS:

article a {
  color: maroon;
}

Nesta lição, você aprenderá por que isso acontece e como a herança é um recurso poderoso para ajudar você a escrever menos CSS.

Fluxo de herança

Vejamos como funciona a herança usando este snippet de HTML:

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

O elemento raiz (<html>) não herdará nada porque é o primeiro elemento do documento. Quando você adiciona CSS ao elemento HTML, ele começa a ser propagado para o documento.

html {
  color: lightslategray;
}

A propriedade color é herdada por padrão por outros elementos. O elemento html tem color: lightslategray. Portanto, todos os elementos que podem herdar cores agora terão uma cor lightslategray.

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

Somente a <p> terá texto em itálico, porque é o elemento aninhado mais profundo. A herança flui apenas para baixo, não para os elementos pais.

Quais propriedades são herdadas por padrão?

Nem todas as propriedades CSS são herdadas por padrão, mas há muitas que são. Como referência, confira a lista completa de propriedades herdadas por padrão, retirada da referência W3 de todas as propriedades CSS:

Como funciona a herança

Cada elemento HTML tem todas as propriedades CSS definidas por padrão com um valor inicial. Um valor inicial é uma propriedade que não é herdada e que aparece como padrão se a cascata não calcular um valor para esse elemento.

As propriedades que podem ser herdadas em cascata, e os elementos filhos recebem um valor calculado que representa o valor do pai. Isso significa que, se um elemento pai tiver font-weight definido como bold, todos os elementos filhos ficarão em negrito, a menos que o font-weight esteja definido como um valor diferente ou a folha de estilo do user agent tenha um valor de font-weight para esse elemento.

Como herdar e controlar explicitamente a herança

A herança pode afetar elementos de maneiras inesperadas. Por isso, o CSS tem ferramentas para ajudar nisso.

A palavra-chave inherit

É possível fazer com que qualquer propriedade herde o valor calculado da mãe com a palavra-chave inherit. Uma maneira útil de usar essa palavra-chave é criar exceções.

strong {
  font-weight: 900;
}

Esse snippet de CSS define todos os elementos <strong> para ter um font-weight de 900, em vez do valor padrão de bold, que seria equivalente a font-weight: 700.

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

A classe .my-component define font-weight como 500. Para fazer com que os elementos <strong> dentro de .my-component também font-weight: 500 adicionem:

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

Agora, os elementos <strong> dentro de .my-component terão um font-weight de 500.

É possível definir explicitamente esse valor, mas, se você usar inherit e o CSS de .my-component mudar no futuro, garanta que seu <strong> fique automaticamente atualizado com ele.

A palavra-chave initial

A herança pode causar problemas com seus elementos, e o initial oferece uma poderosa opção de redefinição.

Você aprendeu anteriormente que cada propriedade tem um valor padrão no CSS. A palavra-chave initial retorna uma propriedade para esse valor inicial padrão.

aside strong {
  font-weight: initial;
}

Esse snippet vai remover o peso em negrito de todos os elementos <strong> dentro de um elemento <aside> e, em vez disso, tornará o peso normal, que é o valor inicial.

A palavra-chave unset

A propriedade unset se comportará de maneira diferente se uma propriedade for herdada por padrão ou não. Se uma propriedade for herdada por padrão, a palavra-chave unset será igual a inherit. Se a propriedade não for herdada por padrão, a palavra-chave unset será igual a initial.

Lembrar quais propriedades CSS são herdadas por padrão pode ser difícil, e unset pode ser útil nesse contexto. Por exemplo, color é herdado por padrão, mas margin não. Então, você pode escrever isso:

/* 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;
}

Agora, o margin será removido, e color voltará a ser o valor calculado herdado.

Também é possível usar o valor unset com a propriedade all. Voltando ao exemplo acima, o que acontecerá se os estilos globais p receberem algumas propriedades extras? Somente a regra que foi definida para margin e color será aplicada.

/* 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;
}

Se você alterar a regra aside p para all: unset, não importa quais estilos globais sejam aplicados a p no futuro, eles sempre serão não definidos.

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

Teste seu conhecimento

Teste seu conhecimento sobre herança

Quais das propriedades a seguir são herdáveis?

animation
As animações não são transmitidas a filhos.
font-size
🎉
color
🎉
text-align
🎉
line-height
🎉

Qual valor se comporta como inherit, a menos que não haja nada para herdar e, em seguida, se comporta como initial?

reset
não é um valor válido, tente novamente.
unset
🎉
superset
não é um valor válido, tente novamente.

Recursos