Pular para o conteúdo
murad.guide

A Web Aberta

Capítulo 30

Pseudo-elementos e interação CSS

4 min de leitura 698 palavras 2 gravuras

Esta é o capítulo 30 de 52 do volume Aprenda a Web. O projeto-fio é a Oficina Costeira, um coletivo fictício de design em João Pessoa. O exemplo está em exemplos/30-pseudo-elementos/. Nada aqui exige JavaScript. Em cada capítulo: leia, copie, mude uma coisa, preveja, recarregue e confira.

O que você vai aprender

Dois pedaços escondidos

Todo elemento tem ::before e ::after. Eles nascem vazios. Sem content, não aparecem. O valor pode ser um espaço, um texto ou "".

.cartao::before {
  content: "";
}

.cartao::after {
  content: "Oficina";
  display: inline-block;
  padding: 0.25em 0.5em;
  background: #0b4f6c;
  color: #fff;
}

Os pseudo-elementos ficam dentro do pai. position: absolute neles mede o ancestral relative.

<!DOCTYPE html>
<html lang="pt-BR">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Detalhe — Oficina Costeira</title>
    <link rel="stylesheet" href="assets/stylesheets/main.css">
  </head>
  <body>
    <article class="cartao">
      <h1>Encontro na orla</h1>
      <p>Ateliê fictício na Praia do Jacaré, João Pessoa.</p>
    </article>
  </body>
</html>

Copie. Mude content do ::after para "Jacaré". Preveja o selo. Recarregue.

Erro comum: esquecer content. A regra de cor e tamanho existe, mas nada desenha.

Marcadores e aspas

A bolinha padrão de ul é difícil de pintar. Tire list-style e coloque o marcador no ::before.

.oficinas {
  list-style: none;
  padding: 0;
}

.oficinas li::before {
  content: "·";
  display: inline-block;
  margin-right: 0.35em;
  color: #c45c26;
}

Citação com aspas curvas, sem span extra:

blockquote {
  position: relative;
}

blockquote::before {
  content: "“";
  font-size: 3rem;
  color: #c45c26;
  position: absolute;
  left: -0.4em;
  top: 0;
}

O texto da citação continua no HTML. A aspa é enfeite. Quem não vê CSS ainda lê a frase.

Hover não é foco

:hover reage ao ponteiro. Teclado não passa por cima. :focus-visible reage quando o foco precisa aparecer — em geral Tab.

a {
  color: #0b4f6c;
}

a:hover {
  color: #c45c26;
}

a:focus-visible,
button:focus-visible {
  outline: 3px solid #c45c26;
  outline-offset: 3px;
}

Não remova o outline sem substituto. O retângulo de 3 px é o combinado deste volume.

:focus-visible evita o anel quando a pessoa clica com o mouse e o navegador julga que o anel não ajuda. O Tab continua óbvio.

Mude outline-offset para 0. Preveja o anel colado no texto. Recarregue. Volte para 3px.

Resumo dos conceitos: ::before, ::after, :hover / :focus

Abrir sem script

:target estiliza o elemento cujo id está no hash da URL.

<p><a href="#aviso">Ler o aviso</a></p>
<p id="aviso" class="aviso">Encontro fictício. Nada é enviado a um servidor.</p>
.aviso:target {
  outline: 3px solid #c45c26;
  background: #fff;
}

Clique no link. A URL ganha #aviso. O parágrafo destaca. Voltar tira o alvo.

details e summary abrem um bloco nativo, com teclado.

<details>
  <summary>Horário do encontro</summary>
  <p>Sábado fictício, 9h, Praia do Jacaré.</p>
</details>

Não use checkbox escondido para fingir um botão. O foco some e o estado não tem nome acessível. Prefira details ou um link :target.

Erro comum: div clicável só com :hover para “abrir o menu”. Sem Tab, sem Enter, sem leitor. Interação de verdade precisa de foco e teclado.

Enfeite, não conteúdo

content não substitui um título. Texto importante fica no HTML. Pseudo-elemento serve para marca, ícone decorativo ou aspa.

attr(data-selo) copia um atributo para content. Continua sendo visual. O leitor pode ignorar. Se a informação importa, escreva no p ou no span.

.cartao::after {
  content: attr(data-selo);
}
<article class="cartao" data-selo="Vagas fictícias">
  <h2>Oficina de cartaz</h2>
</article>

Leia o HTML sem CSS. Se a frase essencial sumir, ela estava no lugar errado.

Ciclo completo na página

Abra o exemplo. Tab até o primeiro link. Confira o anel. Passe o mouse: a cor muda, o anel do Tab não precisa aparecer. Ative um details. Recarregue: o details volta fechado, o :target só permanece se a URL ainda tiver o hash.

Estreite a janela. Os pseudo-elementos não devem cobrir o texto. Se o ::before absoluto invadir o título, aumente padding-left no pai.

Resumo dos conceitos: :hover / :focus, ::after, ::before

Mude o content do marcador para "→". Preveja a lista. Recarregue.

Atividades

  1. O que falta para um ::before aparecer na tela?
  2. Qual pseudo-classe desenha o contorno quando a pessoa usa Tab, sem depender de :hover?
  3. Por que um menu só com :hover na div falha no teclado?
  4. Qual elemento HTML abre e fecha conteúdo sem JavaScript e sem checkbox?
  5. O selo “Vagas fictícias” pode viver só em content? Justifique.

Respostas comentadas

  1. A propriedade content, mesmo que seja "". Sem ela o pseudo-elemento não gera caixa.
  2. :focus-visible, com outline de cerca de 3 px e deslocamento.
  3. div não entra na ordem de Tab. :hover não existe no teclado. Não há nome de botão.
  4. details com summary. Alternativa: link interno e :target.
  5. Não, se a informação importa. content é visual. Coloque o texto no HTML.

Referências

O arquivo completo

Referência do exemplo 30-pseudo-elementos, reproduzida aqui para que você possa conferir sem sair da página.

assets/javascript/simulacao.js

const form=document.querySelector("#simulacao");if(form){form.querySelector("button[type=submit]").disabled=false;form.addEventListener("submit",event=>{event.preventDefault();document.querySelector("#retorno").textContent="Simulação concluída. Nada foi enviado ou guardado.";});}