Além da tag, da classe e do id
Os seletores básicos (p, .aviso, #cabecalho) quebram o galho, mas ficam
curtos assim que o design aperta: "estilize o primeiro item do menu", "só o link
ativo", "as linhas pares da tabela". Para isso o CSS tem seletores muito mais
expressivos, capazes de apontar a um elemento pela sua posição, seu estado
ou seus atributos, sem mexer numa única linha do HTML. E o melhor: cada mudança
você vê na hora na tela.
Combinadores: relações entre elementos
Um combinador relaciona dois seletores segundo a posição dos elementos na árvore do documento.
/* Descendente (espaço): qualquer <a> dentro de um .nav, em qualquer nível */
.nav a { color: teal; }
/* Filho direto (>): apenas os <li> filhos imediatos de .menu */
.menu > li { font-weight: bold; }
/* Irmão adjacente (+): o <p> que vem LOGO depois de um <h2> */
h2 + p { margin-top: 0; }
/* Irmão geral (~): TODOS os <p> irmãos posteriores a um <h2> */
h2 ~ p { color: #555; }
A BselecionaBque esteja dentro deA(em qualquer profundidade).A > Bexige queBseja filho direto deA.A + Bseleciona o primeiro irmãoBimediatamente apósA.A ~ Bseleciona todos os irmãosBque venham depois deA.
O truque para nunca confundir > com um espaço: o espaço é "em algum lugar lá
dentro", o > é "exatamente o filho, sem netos".
Pseudo-classes: selecionar por estado ou posição
Uma pseudo-classe (um único :) aponta a um elemento segundo um estado dinâmico
ou sua posição entre irmãos.
a:hover { text-decoration: underline; } /* ao passar o mouse */
input:focus { outline: 2px solid royalblue; } /* ao receber o foco */
li:first-child { font-weight: bold; } /* o primeiro filho */
li:last-child { border-bottom: none; } /* o último filho */
li:nth-child(2) { background: #eef; } /* o 2º filho */
li:nth-child(odd) { background: #f7f7f7; } /* ímpares: 1, 3, 5... */
p:not(.destacado) { opacity: 0.7; } /* todos menos .destacado */
:nth-child() aceita um número, as palavras odd/even, ou uma fórmula
an+b (por exemplo 3n para um a cada três). É seu melhor aliado para aquelas
tabelas de linhas alternadas, sem marcar nenhuma classe na mão.
Pseudo-elementos: estilizar partes geradas
Um pseudo-elemento (:: duplo) estiliza uma parte específica do elemento ou
gera conteúdo. ::before e ::after inserem conteúdo e exigem a
propriedade content.
.preco::before { content: "R$ "; color: green; }
.link-externo::after { content: " ↗"; }
p::first-line { font-weight: bold; }
Sem content, os pseudo-elementos ::before/::after não são exibidos. É o
esquecimento número um: a regra parece certinha, mas na tela não aparece nada
porque falta o content. Lembre disso e você economiza um bom tempo de
confusão.
Seletores de atributo
Apontam a elementos segundo a presença ou o valor de um atributo HTML.
input[type="text"] { border: 1px solid #ccc; } /* valor exato */
a[target] { font-weight: bold; } /* tenha o atributo */
a[href^="https"] { color: green; } /* começa com */
img[src$=".png"] { border: 1px solid #ddd; } /* termina em */
a[href*="exemplo"] { color: orange; } /* contém */
Combinando esses seletores você aponta com precisão de franco-atirador a quase qualquer elemento sem sujar o HTML com classes de enchimento. Menos classes inventadas, CSS mais limpo.