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!
📑 Índice do Conteúdo
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):
/* 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: "★ ";oucontent: " • ";. - 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:
.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):
.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:
/* 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:
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:
<!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:
8. Resumo e Próximos Passos
- Pseudo-elementos (usando
::) criam nós virtuais ou estilizam subpartes sem alterar o código HTML. ::beforee::aftersã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).::markerestiliza as bolinhas e numerações de listas de forma nativa e limpa.::selectioncustomiza 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)!