Herança

The CSS Podcast - 005: Inheritance

Digamos que você acabou de escrever um CSS para fazer com que os elementos pareçam 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, adicione 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 está na cor esperada. Como isso aconteceu?

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

article a {
  color: maroon;
}

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

Fluxo de herança

Vamos conferir como a herança funciona, usando este snippet de HTML:

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

O elemento raiz (<html>) não herda nada porque é o primeiro elemento do documento. Adicione um pouco de CSS ao elemento HTML, e ele começa a cair em cascata no 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 a cor agora terão uma cor de lightslategray.

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

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

Quais propriedades são herdadas por padrão?

Nem todas as propriedades do CSS são herdadas por padrão, mas muitas são. Para referência, aqui está a lista completa de propriedades herdadas por padrão, extraida da referência W3 de todas as propriedades CSS:

Como a herança funciona

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 aparece como padrão se a cascata não conseguir calcular um valor para esse elemento.

As propriedades que podem ser herdadas são aplicadas em cascata para baixo, e os elementos filhos recebem um valor calculado que representa o valor do elemento pai. Isso significa que, se um elemento pai tiver font-weight definido como bold, todos os elementos filhos serão em negrito, a menos que o font-weight deles seja definido como um valor diferente ou que a folha de estilos do agente do usuário tenha um valor para font-weight para esse elemento.

Como herdar e controlar a herança de forma explícita

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 computado da entidade pai 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 que todos os elementos <strong> tenham um font-weight de 900, em vez do valor padrão bold, que seria o equivalente de font-weight: 700.

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

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

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

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

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

A palavra-chave initial

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

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

aside strong {
  font-weight: initial;
}

Esse snippet remove o peso em negrito de todos os elementos <strong> dentro de um elemento <aside> e os torna de peso normal, que é o valor inicial.

A palavra-chave unset

A propriedade unset se comporta de maneira diferente se uma propriedade é 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 do CSS são herdadas por padrão pode ser difícil, unset pode ser útil nesse contexto. Por exemplo, color é herdado por padrão, mas margin não é. Você pode escrever o seguinte:

/* 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 foi removido e o color voltou a ser o valor computado herdado.

Você também pode usar o valor unset com a propriedade all. Voltando ao exemplo acima, o que acontece se os estilos p globais receberem mais algumas propriedades? Somente a regra 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ê mudar a regra aside p para all: unset, não importa quais estilos globais são aplicados ao p no futuro. Eles sempre serão redefinidos.

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

Teste seu conhecimento

Teste seus conhecimentos sobre herança

Quais das propriedades a seguir são herdadas por padrão?

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

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

reset
não é um valor válido. Tente de novo.
unset
🎉
superset
não é um valor válido. Tente de novo.

Recursos