Resumindo
- Um efeito hover com gradiente em CSS não sai com uma transição de background-image, porque os navegadores trocam gradientes na hora em vez de interpolá-los.
- A técnica mais compatível é um gradiente maior que o elemento com transição em background-position, que desliza as novas cores para a vista.
- Registrar paradas de cor ou ângulos com @property permite que o navegador faça a transição suavemente, e funciona em todos os principais navegadores atuais.
- Esmaecer a opacidade de um segundo gradiente num pseudo-elemento é a técnica mais barata de renderizar, porque mudanças de opacidade não exigem repintura.
- Efeitos hover devem ficar dentro de uma media query de hover e respeitar prefers-reduced-motion.
Nesta página
Um efeito hover com gradiente em CSS exige um contorno, porque os navegadores não fazem transição de background-image: mude o gradiente no :hover e ele troca de uma vez. Quatro técnicas dão um resultado suave. Deslizar um gradiente maior que o elemento com background-position, animar paradas de cor registradas com @property, fazer crossfade de um segundo gradiente num pseudo-elemento ou mover um brilho radial junto com o cursor. Cada uma serve para elementos diferentes, e todas estão abaixo com código.
Por que transition não funciona em gradientes
Para o navegador, um gradiente é uma imagem. Ele sabe interpolar um número ou uma cor, mas não uma imagem em outra, então background-image não é interpolado e o novo gradiente substitui o antigo instantaneamente. Propriedades personalizadas usadas dentro do gradiente se comportam do mesmo jeito, a menos que você as registre, porque uma propriedade não registrada é só texto.
/* This snaps, with no easing */
.btn {
background-image: linear-gradient(135deg, #1e1b4b, #6d28d9);
transition: background-image 400ms ease;
}
.btn:hover {
background-image: linear-gradient(135deg, #6d28d9, #f472b6);
}Técnica 1: deslizar um gradiente maior
Deixe o fundo maior que o elemento, pinte os dois estados nele e depois mova-o. background-position aceita transição, então as novas cores deslizam para dentro. Funciona em todos os navegadores e não precisa de registro.
.btn {
background-image: linear-gradient(90deg, #1e1b4b 0%, #6d28d9 50%, #f472b6 100%);
background-size: 200% 100%;
background-position: 0% 50%;
transition: background-position 500ms ease;
}
.btn:hover {
background-position: 100% 50%;
}linear-gradient(90deg, #1e1b4b 0%, #6d28d9 50%, #f472b6 100%)O movimento parece uma varredura, o que combina com botões e links. É menos convincente em cards grandes, onde dá para ver o gradiente viajando. Animar background-position exige repintura, o que tudo bem em elementos pequenos; para uma superfície grande, use a técnica 3. Botões com gradiente em CSS traz mais padrões de botão baseados nisso.
Técnica 2: animar paradas de cor com @property
Registre as cores das paradas como propriedades personalizadas tipadas e o navegador consegue interpolá-las. O gradiente então muda de cor no lugar, sem deslizar. @property funciona em todos os principais navegadores atuais; os mais antigos simplesmente trocam de uma vez, o que é uma alternativa aceitável para um hover. As regras de registro estão em CSS @property.
@property --stop-a {
syntax: "<color>";
inherits: false;
initial-value: #1e1b4b;
}
@property --stop-b {
syntax: "<color>";
inherits: false;
initial-value: #6d28d9;
}
.card {
background-image: linear-gradient(135deg, var(--stop-a), var(--stop-b));
transition: --stop-a 450ms ease, --stop-b 450ms ease;
}
.card:hover {
--stop-a: #6d28d9;
--stop-b: #f472b6;
}O mesmo truque anima o ângulo. Registre --angle com syntax: "<angle>", use-o em linear-gradient(var(--angle), ...) e mude-o no hover: um gradiente que gira de 135 para 225 graus quando o ponteiro chega é um toque sutil e refinado para cards e bordas com gradiente.
As duas técnicas até aqui também funcionam em texto com gradiente. Texto recortado com background-clip: text mostra o que o fundo fizer, então um deslize ou uma transição de paradas num título faz a cor correr pelas letras no hover. Mantenha a mudança suave em títulos que as pessoas precisam ler e garanta que os dois estados tenham contraste com a página.
Técnica 3: crossfade entre dois gradientes
Coloque o gradiente do hover num pseudo-elemento acima da base e esmaeça a opacidade dele. Mudanças de opacidade são tratadas pelo compositor sem repintura, então esta é a escolha mais suave para cards grandes, painéis de hero e qualquer coisa numa grade longa.
.tile {
position: relative;
isolation: isolate;
background-image: linear-gradient(135deg, #1e1b4b, #6d28d9);
}
.tile::before {
content: "";
position: absolute;
inset: 0;
z-index: -1;
border-radius: inherit;
background-image: linear-gradient(135deg, #6d28d9, #f472b6);
opacity: 0;
transition: opacity 400ms ease;
}
.tile:hover::before {
opacity: 1;
}z-index: -1 com isolation: isolate mantém o pseudo-elemento atrás do texto do bloco, mas acima do gradiente de base.Técnica 4: um brilho que segue o cursor
Um gradiente radial posicionado com propriedades personalizadas pode acompanhar o ponteiro. Defina --x e --y com um pequeno script e a luz se move com a mão. Mantenha-o suave e longe do texto: deve parecer luz sobre uma superfície, nunca um halo em volta das palavras.
.panel {
background-image:
radial-gradient(circle 220px at var(--x, 50%) var(--y, 50%), rgb(244 114 182 / 0.35), transparent 70%),
linear-gradient(135deg, #1e1b4b, #312e81);
}
/* JavaScript:
panel.addEventListener("pointermove", (e) => {
const r = panel.getBoundingClientRect();
panel.style.setProperty("--x", `${e.clientX - r.left}px`);
panel.style.setProperty("--y", `${e.clientY - r.top}px`);
});
*/Como escolher a técnica
Aparência
Custo de renderização
Ideal para
Aparência
Custo de renderização
Ideal para
Aparência
Custo de renderização
Ideal para
Aparência
Custo de renderização
Ideal para
Para gradientes que se movem sozinhos, e não no hover, veja gradientes animados em CSS. Para um panorama do que custa tempo de pintura, veja desempenho de gradientes CSS.
Telas sensíveis ao toque e movimento reduzido
Evite
- Estilos de hover que ficam presos depois de um toque no celular
- Informações que só aparecem no hover
- Animações de hover longas e em loop
- Ignorar a configuração de movimento reduzido
Faça
- Envolva as regras de hover em
@media (hover: hover) - Mostre o mesmo estado em
:activepara toque - Mantenha as transições entre 200 e 500ms
- Corte o movimento sob
prefers-reduced-motione mantenha a mudança de cor
@media (hover: hover) {
.btn:hover { background-position: 100% 50%; }
}
@media (prefers-reduced-motion: reduce) {
.btn { transition: none; }
}Efeitos hover dão vida a um site. Em posts de redes sociais não há ponteiro, então o movimento precisa viver no próprio design. Os Marks do Gradiently podem ter seu próprio movimento suave e, com o Pro, um design é exportado como MP4, WebM ou GIF onde o navegador permite gravar, pronto para um story ou um post.
Perguntas frequentes
Dá para fazer transição de um gradiente CSS no hover?
Não diretamente. background-image muda na hora. Faça a transição de background-position num gradiente maior, anime paradas registradas com @property ou esmaeça a opacidade de um segundo gradiente.
Como faço um botão com gradiente mudar de cor suavemente no hover?
Use background-size: 200% 100% com um gradiente de três paradas e faça a transição de background-position de 0% 50% para 100% 50% no hover.
O @property funciona em todos os navegadores?
Funciona nas versões atuais do Chrome, Edge, Safari e Firefox. Navegadores antigos trocam de estado de uma vez, sem suavizar.
Qual é o efeito hover com gradiente de melhor desempenho?
Um crossfade de opacidade: o gradiente do hover fica num pseudo-elemento e só a opacidade dele muda, o que evita repintura.
Efeitos hover com gradiente devem respeitar o movimento reduzido?
Sim. Sob prefers-reduced-motion: reduce, remova o movimento e mantenha uma mudança de cor simples.
Escrito pelo Gradiently
A equipe por trás do Gradiently, uma ferramenta de design criada em torno dos Marks: gradientes vivos que fazem tudo o que você cria ter a sua cara.
Ver nosso perfil