Focus, Transition, Cursor e Hover CSS: guia com exemplos interativos

Passe o mouse sobre um botão de qualquer site profissional. Ele muda de cor, talvez suba um pouquinho, e a setinha do mouse vira uma mãozinha. Clique em um campo de formulário e a borda se acende. Nada disso é enfeite: são sinais que dizem ao usuário “isso aqui é clicável” ou “você está digitando neste campo”. Uma página sem esses sinais parece morta, mesmo com um visual bonito.

Neste artigo você vai aprender as quatro ferramentas do CSS que dão vida à interface: as pseudo-classes :hover e :focus, a propriedade transition e a propriedade cursor. E pode testar tudo aqui mesmo, porque os exemplos são de verdade.

O que é uma pseudo-classe?

Até agora selecionamos elementos pelo que eles são: uma tag (p), uma classe (.card), um ID (#promo). Uma pseudo-classe seleciona um elemento pelo estado em que ele está: com o mouse em cima, selecionado, já visitado… Ela é escrita com dois-pontos logo depois do seletor, sem espaço:

Anatomia de um seletor com pseudo-classe: .botao:hover .botao : hover { … } quem? (seletor) dois-pontos, sem espaço quando? (estado)
Lê-se: “aplique estas regras ao .botao quando o mouse estiver sobre ele”.

:hover — quando o mouse passa por cima

O :hover é ativado enquanto o ponteiro do mouse está sobre o elemento. Você escreve o estilo normal e, separado, o estilo do estado hover:

.botao {
  background-color: #1a73c9;   /* estado normal */
  color: #fff;
}

.botao:hover {
  background-color: #f68e36;   /* com o mouse em cima */
  color: #2b2d42;
}
Passe o mouse no botão Fazer pedido

Repare que o :hover só precisa trazer o que muda. A cor do texto, o padding e todo o resto continuam vindo da regra .botao.

O hover não precisa mudar o próprio elemento

Um truque muito usado: passar o mouse em um elemento e alterar outro que está dentro dele. Basta colocar o hover no pai e escrever o filho depois, com espaço:

/* mouse no card → o título dele muda de cor */
.card:hover h4 {
  color: #b85309;
}
Atenção ao celular: na tela de toque não existe “passar o mouse”. O hover até dispara no toque, mas de forma inconsistente. Por isso, nunca esconda informação importante atrás de um hover — use-o como reforço visual, não como única forma de mostrar algo.

:focus — quando o elemento está selecionado

O :focus é ativado quando um elemento recebe o foco: você clicou em um campo para digitar ou chegou nele apertando a tecla Tab. Ele vale para elementos interativos: input, textarea, select, button e links.

.campo {
  border: 2px solid #fab875;
}

.campo:focus {
  outline: none;                            /* remove o contorno padrão */
  border-color: #1a73c9;
  box-shadow: 0 0 0 4px rgba(54, 158, 246, 0.3);   /* "brilho" em volta */
}
Clique no campo ou chegue nele com a tecla Tab

Nunca remova o foco sem colocar outro no lugar

Por padrão, o navegador desenha um contorno (outline) em volta do elemento focado. Muita gente acha feio e escreve outline: none… e para por aí. O problema: quem navega pelo teclado — pessoas com deficiência motora, usuários de leitores de tela, ou simplesmente quem prefere o Tab — perde completamente a noção de onde está na página.

A regra é simples: se tirar o outline, coloque outro indicador visível (borda, sombra, cor de fundo). No exemplo acima, o box-shadow faz esse papel.

Bônus: :focus-visible. Essa variação só mostra o indicador quando o foco veio do teclado, e não do clique do mouse. É a forma moderna de ter botões limpos para quem usa mouse sem prejudicar quem usa Tab:
.botao:focus-visible {
  outline: 3px solid #1a73c9;
  outline-offset: 4px;
}

transition — a mudança suave

Até aqui, as mudanças acontecem de uma vez, num “estalo”. A propriedade transition faz a mudança acontecer aos poucos, ao longo de um tempo. Compare:

Passe o mouse nos dois botões
Sem transition Com transition

O CSS dos dois botões é idêntico, com uma única diferença: a linha do transition.

.botao {
  background-color: #1a73c9;
  color: #fff;
  transition: background-color 0.4s ease, color 0.4s ease, transform 0.4s ease;
}

.botao:hover {
  background-color: #f68e36;
  color: #2b2d42;
  transform: translateY(-4px);   /* sobe 4px */
}
Onde colocar o transition? No estado normal (.botao), não no :hover. Assim a animação acontece nos dois sentidos: quando o mouse entra e quando sai. Se você colocar só no :hover, a volta será instantânea.

A sintaxe do transition

Partes da propriedade transition: propriedade, duração, função de tempo e atraso transition: background-color 0.4s ease 0s ; 1 · o que anima 2 · quanto tempo 3 · ritmo 4 · espera Só os dois primeiros são obrigatórios na prática.
As quatro partes do transition, nesta ordem.
  1. Propriedade: qual propriedade vai animar (background-color, transform, color…). Use all para animar todas, mas prefira listar só as que mudam.
  2. Duração: quanto tempo leva, em segundos (0.3s) ou milissegundos (300ms). Para interfaces, entre 0.2s e 0.4s costuma ficar natural. Acima de 0.6s o site parece lento.
  3. Função de tempo: o ritmo da animação, explicado logo abaixo. Se omitir, vale ease.
  4. Atraso (delay): quanto esperar antes de começar. Se omitir, vale 0s.

Para animar mais de uma propriedade com tempos diferentes, separe com vírgula:

transition: background-color 0.3s ease, transform 0.2s ease-out;

As funções de tempo (timing functions)

Todas as bolinhas abaixo levam o mesmo tempo para chegar ao fim. O que muda é o ritmo: onde elas aceleram e onde freiam.

Passe o mouse sobre esta área e compare
linear
ease
ease-in
ease-out
ease-in-out
ValorRitmoSensação
linearVelocidade constanteMecânica, de robô
easeAcelera rápido e freia devagar (padrão)Natural, serve para quase tudo
ease-inComeça devagar e termina rápidoBom para coisas que saem da tela
ease-outComeça rápido e termina devagarBom para coisas que entram ou respondem ao usuário
ease-in-outDevagar nas duas pontasSuave, elegante

O que dá e o que não dá para animar

O transition só funciona entre valores numéricos ou cores, porque o navegador precisa calcular os “passos do meio”. Cores, tamanhos, opacidade, sombras e transform animam bem. Já trocar a fonte de Arial para Verdana não anima: não existe “meia fonte”. Nesses casos a mudança acontece de uma vez, mesmo com transition.

Dica de desempenho: prefira animar transform e opacity. Para mover um elemento, transform: translateY(-4px) é muito mais leve para o navegador do que mudar margin-top ou top, que obrigam a recalcular o layout da página inteira.

cursor — o formato do ponteiro

A propriedade cursor define qual ícone o mouse mostra quando está sobre o elemento. Ela é a forma mais direta de dizer ao usuário o que acontece se ele clicar. Passe o mouse em cada caixa:

Passe o mouse em cada caixa
defaultseta padrão
pointerclicável
texttexto editável
not-allowedbloqueado
waitaguarde
helpajuda
movearrastar
grabpegar
zoom-inampliar
crosshairmira

Os mais usados no dia a dia:

.card-clicavel {
  cursor: pointer;          /* mãozinha: "pode clicar aqui" */
}

button:disabled {
  cursor: not-allowed;      /* círculo cortado: "não dá para clicar" */
  opacity: 0.5;
}

abbr[title] {
  cursor: help;             /* interrogação: tem uma explicação no title */
}
Use o cursor com honestidade. Links (<a href>) já ganham a mãozinha automaticamente. Mas se você transformar uma <div> em algo clicável, coloque cursor: pointer. E o contrário também vale: não coloque mãozinha em algo que não faz nada ao ser clicado — isso frustra o usuário.

Juntando tudo: um card de cardápio interativo

Agora as quatro ferramentas trabalhando juntas. Passe o mouse no card e no botão, e experimente também chegar no botão com a tecla Tab:

Cappuccino

Café, leite vaporizado e canela.

R$ 9,50

O que cada uma faz no card:

  • :hover no card faz ele subir, ganhar sombra e trocar a cor da borda; no botão, troca a cor de fundo;
  • transition deixa essas mudanças suaves, na ida e na volta;
  • cursor: pointer fica só no botão, que é o que realmente faz algo ao ser clicado;
  • :focus-visible mostra um contorno no botão para quem navega pelo teclado.

Código completo do exemplo

Salve os dois arquivos na mesma pasta e abra o index.html no navegador.

index.html
<!DOCTYPE html>
<html lang="pt-BR">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Cafeteria Grão Dourado</title>
  <link rel="stylesheet" href="style.css">
</head>
<body>

  <main>
    <h1>☕ Cardápio</h1>

    <div class="card">
      <h4>Espresso</h4>
      <p>Café curto e intenso.</p>
      <span class="preco">R$ 6,00</span>
      <button type="button" class="botao">Pedir</button>
    </div>

    <div class="card">
      <h4>Cappuccino</h4>
      <p>Café, leite vaporizado e canela.</p>
      <span class="preco">R$ 9,50</span>
      <button type="button" class="botao">Pedir</button>
    </div>

    <div class="card">
      <h4>Bolo de cenoura</h4>
      <p>Volta amanhã!</p>
      <span class="preco">R$ 7,00</span>
      <button type="button" class="botao" disabled>Esgotado</button>
    </div>

    <form class="contato">
      <h2>Receba nossas promoções</h2>
      <label for="email">Seu e-mail</label>
      <input type="email" id="email" class="campo" placeholder="voce@email.com">
      <button type="submit" class="botao">Quero receber</button>
    </form>
  </main>

</body>
</html>
style.css
/* ===== Página ===== */
body {
  margin: 0;
  font-family: Arial, sans-serif;
  background-color: #f8f9fa;
  color: #2b2d42;
}

main {
  max-width: 480px;
  margin: 0 auto;
  padding: 24px 16px;
}

h1, h2 {
  color: #1a73c9;
}

/* ===== Cards ===== */
.card {
  background-color: #ffffff;
  border: 2px solid #fab875;
  border-radius: 12px;
  padding: 20px;
  margin-bottom: 20px;
  transition: transform 0.25s ease,             /* TRANSITION */
              box-shadow 0.25s ease,
              border-color 0.25s ease;
}

.card h4 {
  margin: 0 0 4px;
  color: #1a73c9;
  font-size: 1.15em;
  transition: color 0.25s ease;
}

.card p {
  margin: 0 0 12px;
  color: #5c6075;
}

.preco {
  font-weight: bold;
  color: #1a73c9;
  margin-right: 12px;
}

.card:hover {                                   /* HOVER */
  transform: translateY(-6px);
  box-shadow: 0 12px 24px rgba(43, 45, 66, 0.18);
  border-color: #f68e36;
}

.card:hover h4 {                                /* HOVER no pai muda o filho */
  color: #b85309;
}

/* ===== Botões ===== */
.botao {
  padding: 10px 22px;
  border: none;
  border-radius: 8px;
  background-color: #1a73c9;
  color: #ffffff;
  font-size: 16px;
  font-weight: bold;
  cursor: pointer;                              /* CURSOR */
  transition: background-color 0.3s ease, color 0.3s ease, transform 0.2s ease-out;
}

.botao:hover {
  background-color: #f68e36;
  color: #2b2d42;
  transform: translateY(-2px);
}

.botao:focus-visible {                          /* FOCO pelo teclado */
  outline: 3px solid #1a73c9;
  outline-offset: 3px;
}

.botao:disabled {
  background-color: #c3c7d0;
  cursor: not-allowed;                          /* CURSOR de bloqueado */
  transform: none;
}

/* ===== Formulário ===== */
.contato {
  margin-top: 40px;
}

label {
  font-weight: bold;
}

.campo {
  width: 100%;
  box-sizing: border-box;
  margin: 6px 0 12px;
  padding: 12px 14px;
  border: 2px solid #fab875;
  border-radius: 8px;
  font-size: 16px;
  font-family: inherit;
  transition: border-color 0.2s ease, box-shadow 0.2s ease;
}

.campo:focus {                                  /* FOCUS */
  outline: none;
  border-color: #1a73c9;
  box-shadow: 0 0 0 4px rgba(54, 158, 246, 0.3);
}

Resumo rápido

RecursoO que fazExemplo
:hoverEstilo enquanto o mouse está sobre o elemento.botao:hover { … }
:focusEstilo quando o elemento está selecionado (clique ou Tab)input:focus { … }
:focus-visibleFoco só quando vem do teclado.card:focus-visible { … }
transitionFaz a mudança de estilo acontecer aos poucostransition: color 0.3s ease;
cursorDefine o ícone do ponteiro sobre o elementocursor: pointer;

Desafio para praticar

  1. Crie três botões: um que muda de cor no hover, um que cresce (transform: scale(1.1)) e um que ganha sombra. Todos com transition de 0.3s.
  2. Teste as cinco funções de tempo no botão que cresce. Qual parece mais natural para você?
  3. Monte um formulário com três campos e navegue entre eles usando apenas a tecla Tab. Dá para ver claramente onde você está? Se não, crie um estilo de :focus.
  4. Adicione um botão desabilitado com cursor: not-allowed e confira se o hover dele está desligado.

Washington Paiva — instrutor de Desenvolvimento de Sistemas · washington.pro.br

Compartilhe:

Profissional engajado com as últimas tendências tecnológicas e de gestão, buscando continuamente aprimorar suas competências e compartilhar seu conhecimento.

Publicar comentário