A versão curta
- Um efeito hover com gradiente CSS não se faz com transition em background-image, porque os browsers trocam os gradientes instantaneamente em vez de os interpolar.
- A técnica mais compatível é um gradiente sobredimensionado com transition em background-position, que desliza as novas cores para a vista.
- Registar paragens de cor ou ângulos com @property permite ao browser fazer a transição suavemente, e funciona em todos os principais browsers atuais.
- Esbater a opacidade de um segundo gradiente num pseudo-elemento é a técnica mais barata de renderizar, porque as mudanças de opacidade não obrigam a repintar.
- Os efeitos hover devem estar dentro de uma media query de hover e respeitar prefers-reduced-motion.
Nesta página
Um efeito hover com gradiente CSS precisa de um truque, porque os browsers não fazem transition de background-image: muda o gradiente em :hover e ele salta. Quatro técnicas dão um resultado suave. Deslizar um gradiente sobredimensionado com background-position, animar paragens de cor registadas com @property, fundir um segundo gradiente num pseudo-elemento, ou mover um brilho radial com o cursor. Cada uma serve elementos diferentes, e todas estão abaixo com código.
Porque é que o transition não funciona em gradientes
Para o browser, um gradiente é uma imagem. Sabe interpolar um número ou uma cor, mas não uma imagem noutra, por isso background-image não é interpolado e o novo gradiente substitui o antigo de imediato. As propriedades personalizadas usadas dentro do gradiente comportam-se da mesma forma, a não ser que as registes, porque uma propriedade não registada é apenas 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 sobredimensionado
Faz o fundo maior do que o elemento, pinta lá dentro os dois estados e depois move-o. O background-position pode ter transition, por isso as novas cores deslizam para dentro. Funciona em todos os browsers e não precisa de registo.
.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 lê-se como uma varredura, o que serve botões e ligações. É menos convincente em cartões grandes, onde se vê o gradiente a viajar. Animar background-position obriga a repintar, o que não é problema em elementos pequenos; para uma superfície grande, usa a técnica 3. Botões com gradiente em CSS tem mais padrões de botões construídos sobre isto.
Técnica 2: animar paragens de cor com @property
Regista as cores das paragens como propriedades personalizadas tipadas e o browser consegue interpolá-las. O gradiente muda então de cor no mesmo sítio, sem deslizar. O @property funciona em todos os principais browsers atuais; os mais antigos limitam-se a saltar, o que é um recurso aceitável para um hover. As regras de registo 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. Regista --angle com syntax: "<angle>", usa-o em linear-gradient(var(--angle), ...) e muda-o no hover: um gradiente que roda de 135 para 225 graus quando o ponteiro chega é um toque subtil e cuidado para cartões e contornos com gradiente.
As duas técnicas até aqui também funcionam em texto com gradiente. O texto recortado com background-clip: text mostra o que o fundo fizer, por isso um deslize ou uma transição de paragens num título faz a cor correr pelas letras no hover. Mantém a mudança suave em títulos que as pessoas precisam de ler e garante que os dois estados têm contraste suficiente com a página.
Técnica 3: fundir dois gradientes
Põe o gradiente de hover num pseudo-elemento por cima da base e esbate a sua opacidade. As mudanças de opacidade são tratadas pelo compositor sem repintar, por isso esta é a escolha mais suave para cartões grandes, painéis de destaque e tudo o que esteja numa grelha 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 por cima do gradiente de base.Técnica 4: um brilho que segue o cursor
Um gradiente radial posicionado com propriedades personalizadas consegue seguir o ponteiro. Define --x e --y a partir de um pequeno script e a luz acompanha a mão. Mantém-no suave e longe do texto: deve parecer luz sobre uma superfície, nunca um halo à 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`);
});
*/Escolher uma técnica
Parece
Custo de renderização
Ideal para
Parece
Custo de renderização
Ideal para
Parece
Custo de renderização
Ideal para
Parece
Custo de renderização
Ideal para
Para gradientes que se movem sozinhos e não no hover, vê gradientes animados em CSS. Para uma visão mais ampla do que custa tempo de pintura, vê desempenho dos gradientes CSS.
Ecrãs táteis e movimento reduzido
Evita
- Estilos de hover que ficam presos depois de um toque no telemóvel
- Informação que só aparece no hover
- Animações de hover longas e em ciclo
- Ignorar a definição de movimento reduzido
Faz
- Envolve as regras de hover em
@media (hover: hover) - Mostra o mesmo estado em
:activepara toque - Mantém as transições entre 200 e 500 ms
- Corta o movimento com
prefers-reduced-motione mantém a mudança de cor
@media (hover: hover) {
.btn:hover { background-position: 100% 50%; }
}
@media (prefers-reduced-motion: reduce) {
.btn { transition: none; }
}Os efeitos hover dão vida a um site. Nas publicações sociais não há ponteiro, por isso o movimento tem de viver no próprio design. Os Marks do Gradiently podem trazer o seu próprio movimento suave e, com o Pro, um design exporta-se em MP4, WebM ou GIF onde o browser suporta gravação, pronto para um story ou uma publicação.
Perguntas frequentes
É possível fazer transition de um gradiente CSS no hover?
Não diretamente. O background-image muda de imediato. Faz transition de background-position num gradiente sobredimensionado, anima paragens registadas com @property ou esbate a opacidade de um segundo gradiente.
Como faço um botão com gradiente mudar de cor suavemente no hover?
Usa background-size: 200% 100% com um gradiente de três paragens e depois faz transition de background-position de 0% 50% para 100% 50% no hover.
O @property funciona em todos os browsers?
Funciona nas versões atuais do Chrome, Edge, Safari e Firefox. Os browsers mais antigos saltam entre estados em vez de os suavizar.
Qual é o efeito hover com gradiente de melhor desempenho?
A fusão por opacidade: o gradiente de hover fica num pseudo-elemento e só muda a sua opacidade, o que evita repintar.
Os efeitos hover com gradiente devem respeitar o movimento reduzido?
Sim. Com prefers-reduced-motion: reduce, retira o movimento e mantém uma simples mudança de cor.
Escrito pela Gradiently
A equipa por trás da Gradiently, uma ferramenta de design construída em torno dos Marks: gradientes vivos que fazem tudo o que crias parecer teu.
Ver o nosso perfil