⚡ Curso de CSS • Web-ZoneWare

Pseudo-elementos no CSS: ::before e ::after | Web Academy

Lição 41 de 50

Pseudo-elementos no CSS: ::before e ::after | Web Academy

Uma das marcas distintivas de um desenvolvedor front-end de alto nível é a capacidade de manter o código HTML 100% semântico e enxuto. No passado, para criar uma fita de destaque em um cartão, um sublinhado elegante que se expande ao passar o mouse ou uma bolinha verde pulsante de status, desenvolvedores enchiam o documento de tags vazias como <span class="circulo"></span>. Os Pseudo-elementos (identificados pelo duplo dois-pontos ::) revolucionaram esse cenário: eles criam elementos visuais virtuais diretamente na árvore de renderização do CSS, sem poluir uma única linha do seu HTML!

1. A Sintaxe Padronizada: Por que Dois Dois-Pontos (::)?

Nas especificações antigas de CSS1 e CSS2, tanto pseudo-classes quanto pseudo-elementos usavam um único caractere :.

A partir do CSS3, a W3C estabeleceu uma fronteira conceitual definitiva:

  • Pseudo-classe (: com um dois-pontos): Mira um estado dinâmico do elemento real (ex.: :hover, :focus, :checked).
  • Pseudo-elemento (:: com dois dois-pontos): Cria um elemento visual virtual ou estiliza uma subparte interna (ex.: ::before, ::after, ::marker, ::selection).

Dica de Boas Práticas: Os navegadores modernos ainda aceitam a sintaxe antiga de um ponto (:before) por razões de retrocompatibilidade com a década de 1990. No entanto, em código moderno profissional e acessível, use SEMPRE o padrão moderno de dois dois-pontos (::before e ::after).

2. Onde Nascem ::before e ::after?

Um dos equívocos mais comuns entre iniciantes é acreditar que ::before fica localizado do lado de fora, antes da tag, e que ::after fica do lado de fora, depois da tag. Isso é falso!

No modelo de renderização do navegador, os pseudo-elementos são inseridos INTERNAMENTE dentro do elemento selecionado:

  • ::before: É renderizado como o primeiríssimo filho interno da caixa, logo antes do texto ou de qualquer outro elemento filho.
  • ::after: É renderizado como o último filho interno da caixa, logo após todo o conteúdo do elemento.

Atenção aos Elementos Vazios (Void Elements): Como ::before e ::after são filhos internos, eles NÃO FUNCIONAM em tags HTML auto-fechadas que não aceitam conteúdo filho no DOM, como <img>, <input>, <br> e <hr>!

3. A Regra de Ouro: A Propriedade content

Existe uma lei inegociável para ::before e ::after: sem a propriedade content, o pseudo-elemento simplesmente NÃO EXISTE e o navegador não desenha absolutamente nada na tela!

Mesmo que você queira criar um quadrado geométrico ou uma linha colorida sem nenhum texto dentro, você deve declarar content: ""; (aspas vazias):

CSS3 10 linhas
/* Cria um indicador visual de status verde antes do texto */
.status-online::before {
  content: "";            /* OBRIGATÓRIO: Sem isso, o elemento não nasce! */
  display: inline-block;  /* Por padrão, pseudo-elementos são inline */
  width: 10px;
  height: 10px;
  background-color: #10b981;
  border-radius: 50%;
  margin-right: 8px;
}

O que a Propriedade content Pode Conter?

  • Aspas Vazias (content: "";): O padrão para formas geométricas decorativas, máscaras e overlays.
  • Texto Fixo ou Emojis: content: "★ "; ou content: " • ";.
  • Leitura Dinâmica de Atributos: content: attr(data-tooltip); permite ler valores de atributos HTML para criar tooltips 100% nativos sem JavaScript!

4. Casos de Uso Clássicos na Indústria

1. Sublinhado Animado no Hover (Underline Expandível)

Em vez de usar o velho e rígido text-decoration: underline, criamos uma linha fina com ::after que se expande do centro para as pontas suavemente:

CSS3 23 linhas
.link-magico {
  position: relative;
  text-decoration: none;
  color: #38bdf8;
}
 
.link-magico::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: -4px;
  width: 100%;
  height: 2px;
  background: #38bdf8;
  transform: scaleX(0); /* Inicialmente invisível (comprimido a zero) */
  transition: transform 0.3s ease;
  transform-origin: right;
}
 
.link-magico:hover::after {
  transform: scaleX(1); /* Expande para 100% da largura no hover */
  transform-origin: left;
}

2. Máscara Escura sobre Imagens (Overlay)

Para escurecer um cartão com imagem de fundo e garantir que o texto branco seja sempre legível (contraste WCAG):

CSS3 17 linhas
.card-com-overlay {
  position: relative;
  overflow: hidden;
}
 
.card-com-overlay::before {
  content: "";
  position: absolute;
  inset: 0; /* Preenche 100% da área do card */
  background: rgba(0, 0, 0, 0.55); /* Máscara semitransparente */
  z-index: 1;
}
 
.card-conteudo {
  position: relative;
  z-index: 2; /* Fica acima da máscara */
}

5. Outros Pseudo-elementos Modernos Essenciais

::selection — A Identidade Visual do Texto Selecionado

Quando o usuário arrasta o mouse para copiar um trecho do seu site, você pode trocar o azul genérico do sistema pela cor da marca da sua empresa:

CSS3 5 linhas
/* Personaliza o grifo de texto do site inteiro */
::selection {
  background-color: #38bdf8;
  color: #0b0f19;
}

::marker — Marcadores de Lista sem Gambiarras

No passado, mudar a cor da bolinha de uma lista <li> exigia remover o estilo nativo e reconstruí-lo do zero. Hoje usamos ::marker:

CSS3 4 linhas
li::marker {
  color: #10b981; /* A bolinha ou número fica verde sem afetar o texto! */
  font-size: 1.1rem;
}

6. Acessibilidade e Leitores de Tela (WCAG 2.2)

Atenção com Textos em Pseudo-elementos: Leitores de tela modernos (como VoiceOver e NVDA) leem em voz alta o texto colocado dentro de content: "..."! Portanto, nunca insira textos críticos apenas no CSS. Se o pseudo-elemento for puramente decorativo, use content: "" para evitar poluir a leitura de usuários cegos.

7. Laboratório Prático: Tooltip Nativo e Efeitos de Pseudo-elementos

No código interativo abaixo, construímos um componente que combina tooltip nativo via attr(), bolinha de status pulsante, marcador de lista customizado e grifo de texto personalizado:

HTML5 111 linhas
<!DOCTYPE html>
<html lang="pt-BR">
<head>
  <meta charset="UTF-8">
  <title>Laboratório de Pseudo-elementos CSS</title>
  <style>
    body {
      font-family: 'Inter', system-ui, sans-serif;
      background: #0b0f19;
      color: #f8fafc;
      padding: 40px;
      margin: 0;
    }
 
    /* 1. SELEÇÃO DE TEXTO PERSONALIZADA (::selection) */
    ::selection {
      background: #f59e0b;
      color: #000;
    }
 
    /* 2. CARD COM STATUS ONLINE (::before) */
    .card-usuario {
      max-width: 440px;
      background: #1e293b;
      border: 1px solid #334155;
      border-radius: 14px;
      padding: 24px;
      margin-bottom: 30px;
    }
 
    .status-badge {
      display: inline-flex;
      align-items: center;
      font-size: 0.85rem;
      font-weight: 600;
      color: #10b981;
      margin-bottom: 12px;
    }
 
    /* Bolinha verde desenhada puramente no CSS */
    .status-badge::before {
      content: "";
      width: 8px;
      height: 8px;
      background: #10b981;
      border-radius: 50%;
      margin-right: 8px;
      box-shadow: 0 0 8px #10b981;
    }
 
    /* 3. TOOLTIP NATIVO SEM JS (::after com attr) */
    .tooltip-link {
      position: relative;
      color: #38bdf8;
      text-decoration: underline;
      cursor: pointer;
      display: inline-block;
    }
 
    .tooltip-link::after {
      content: attr(data-tooltip); /* Lê o texto do atributo HTML! */
      position: absolute;
      bottom: 125%;
      left: 50%;
      transform: translateX(-50%) scale(0.9);
      background: #020617;
      color: #fff;
      font-size: 0.75rem;
      padding: 6px 12px;
      border-radius: 6px;
      white-space: nowrap;
      pointer-events: none;
      opacity: 0;
      transition: opacity 0.2s ease, transform 0.2s ease;
      box-shadow: 0 4px 12px rgba(0,0,0,0.5);
      border: 1px solid #334155;
    }
 
    .tooltip-link:hover::after {
      opacity: 1;
      transform: translateX(-50%) scale(1);
    }
 
    /* 4. MARCADOR DE LISTA CUSTOMIZADO (::marker) */
    ul.lista-recursos li::marker {
      color: #38bdf8;
      font-size: 1.2rem;
    }
  </style>
</head>
<body>
  <h2 style="color:#f1f5f9; margin-top:0;">Demonstração de Pseudo-elementos</h2>
  <p style="color:#94a3b8; font-size:0.9rem;">
    Selecione qualquer trecho deste texto com o mouse para ver o <code>::selection</code> amarelo em ação!
  </p>
 
  <div class="card-usuario">
    <div class="status-badge">Servidor Ativo</div>
    <h3 style="margin:0 0 10px 0;">Plataforma WebZoneWare</h3>
    <p style="color:#94a3b8; font-size:0.9rem; line-height:1.6;">
      Passe o mouse sobre esta <span class="tooltip-link" data-tooltip="⚡ Dica de Engenharia: 100% puro CSS!">palavra com tooltip</span> para ver o texto flutuante gerado via <code>content: attr()</code>.
    </p>
 
    <ul class="lista-recursos" style="color:#cbd5e1; font-size:0.9rem;">
      <li>CSS Grid 2D Completo</li>
      <li>Flexbox Unidimensional</li>
      <li>Acessibilidade WCAG 2.2</li>
    </ul>
  </div>
</body>
</html>

Abra este laboratório no Playground IDE e teste passar o cursor sobre a palavra com tooltip e selecionar o texto para comprovar a elegância dos pseudo-elementos:

⚡ Abrir no Playground IDE →

8. Resumo e Próximos Passos

  • Pseudo-elementos (usando ::) criam nós virtuais ou estilizam subpartes sem alterar o código HTML.
  • ::before e ::after são inseridos como o primeiro e o último filho interno da caixa selecionada.
  • A propriedade content: "" é estritamente obrigatória; sem ela, o pseudo-elemento não é renderizado.
  • content: attr(nome) permite ler dados de atributos HTML dinamicamente (como data-tooltips).
  • ::marker estiliza as bolinhas e numerações de listas de forma nativa e limpa.
  • ::selection customiza as cores do texto grifado pelo cursor do usuário.

Próximo Passo: Agora que você pode criar elementos visuais no CSS, como movê-los, girá-los, esticá-los e criar sensações de profundidade em 3D? Na Lição 42, desvendaremos as Transformações 2D e 3D no CSS (translate, rotate, scale, skew e perspective)!

Rolar para cima